תפעול וניסויי עומס מתמשכים¶
שירות שעבר benchmark של דקה יכול להיכשל אחרי שעתיים בגלל retention, fragmentation, דליפת fd או תור שהולך ומתרחב. נבנה ניסוי שמבדיל בין חימום, עומס יציב, קפיצה ועומס ארוך, ונגדיר מה המפעיל צריך לעשות כאשר המדדים יוצאים מן התחום.
ה־p99 אומר שמתחת לערך מסוים נמצאות בערך 99% מן הדגימות לפי שיטת החישוב שנבחרה. הוא אינו אומר שכל בקשה תסתיים בזמן הזה. אם נאסוף רק בקשות שהצליחו, נתעלם בדיוק מן הבקשות שהמתינו עד timeout. לכן הדוח יכלול מספר ניסיונות, הצלחות, דחיות, timeouts והגדרת נקודת המדידה.
הקוד הבא מחשב nearest-rank p99 עבור קבוצה קטנה של דגימות מיקרו־שניות. זהו כלי לקריאת תוצאות מעבדה, ולא histogram בלתי מוגבל בתוך שירות production.
fn p99(samples: &mut [u64]) -> Option<u64> {
if samples.is_empty() { return None; }
samples.sort_unstable();
let rank = samples.len().checked_mul(99)?.checked_add(99)? / 100;
Some(samples[rank - 1])
}
fn main() {
let mut values: Vec<u64> = (1..=100).collect();
assert_eq!(p99(&mut values), Some(99));
assert_eq!(p99(&mut []), None);
println!("p99={:?}", p99(&mut values));
}
מאה דגימות אינן מספיקות בדרך כלל להערכה יציבה של זנב עמוק. נרשום את גודל המדגם ונציג גם את המקסימום ואת שיעור הכשלים. אם 5% מן הבקשות נכשלו ב־timeout, p99 של 95% המצליחות אינו מסכם את חוויית כל הלקוחות. אפשר להציג timeouts כקטגוריה מצונזרת ולומר שהזמן שלהם לפחות deadline, בלי להמציא זמן סיום שלא נמדד.
מחולל עומס סגור שולח בקשה חדשה רק אחרי שהקודמת הסתיימה. כשהשירות נתקע, גם קצב היצירה יורד, ולכן הוא עלול להסתיר עומס שהיה ממשיך להגיע בעולם האמיתי. מחולל פתוח מתזמן הגעות לפי שעון, אך צריך להגביל גם את משאביו ולדווח אם הוא עצמו לא עמד בקצב. נמדוד זמן מן המועד המתוכנן או מן השליחה בפועל לפי השאלה שאנו בודקים, ונציין את הבחירה כדי למנוע coordinated omission מוסתר.
בניסוי warmup נפריד page cache, חיבורי רשת, JIT אם יש רכיב אחר וכל מצב פנימי שנבנה בהתחלה. ב־soak נריץ מספיק זמן כדי לעבור כמה מחזורי cleanup ו־compaction של המוצר. ב־spike נעלה את קצב ההגעה ונבדוק שהשירות דוחה עבודה בצורה מוגדרת וחוזר למצב רגיל אחר כך. שירות שמחזיר Busy באופן צפוי יכול לעמוד בחוזה הרוויה גם אם throughput אינו עולה עוד.
נשתמש במזהי בקשה חדשים עבור עומס שמטרתו לבדוק ביצוע עבודה. שימוש חוזר באותם IDs עלול למדוד את מסלול deduplication בלבד ולהציג מהירות מדומה. מנגד ניסוי retry צריך בכוונה לחזור על IDs ולהוכיח שלא נכתבו רשומות נוספות. נפריד את שני ה־workloads ונמדוד גם את גודל היומן ומספר הרשומות.
ה־runbook יתחיל מתצפית ולא משינוי אקראי. במקרה של latency גבוה נבדוק קצב קבלה, queue depth, פעולות commit וזמני דיסק; במקרה של fd exhaustion נבדוק מספר descriptors וקצב פתיחה וסגירה. לפני restart נשמור ראיות שמתאימות לאירוע, אם הדבר אפשרי בלי לפגוע בהגנה על נתונים. קובץ dump יכול להכיל מידע רגיש, ולכן הרשאות ושמירה מוגבלת הן חלק מן התפעול.
בתהליך restore נבחר backup, נאמת checksum וגרסת schema, נשחזר לתיקייה נפרדת ונריץ recovery ובדיקת קריאה לפני החלפת המצב הפעיל. התיעוד של proc ושל systemd-coredump מספק כלי אבחון. מבחן ההעברה למפעיל אחר יוכיח שההוראות מספיקות בלי ידע שלא נכתב.