כשמשלבים שירות קצה עורפי עם Application Load Balancer, חשוב למדוד את הביצועים של שירות הקצה העורפי בנפרד, בלי איזון עומסים. בדיקות עומס בתנאים מבוקרים עוזרות להעריך את ההשפעה של תכנון הקיבולת על מימדים שונים של הביצועים, כמו קצב העברת הנתונים והשהיה. תכנון קיבולת מדוקדק עדיין עלול להוביל להערכת חסר של הביקוש בפועל, ולכן מומלץ להשתמש בבדיקות עומס כדי לקבוע באופן יזום איך הזמינות של שירות מושפעת כשמערכת נתונה בעומס יתר.
יעדים של בדיקות טעינה
בדיקת עומס טיפוסית מודדת את ההתנהגות של שירות ה-Backend שגלוי לגורמים חיצוניים, בממדים שונים של עומס. הנה כמה מהמאפיינים הרלוונטיים ביותר של הבדיקה הזו:
- קצב העברת הנתונים של הבקשות: מספר הבקשות שמועברות בשנייה.
- מקבילות של בקשות: מספר הבקשות שעוברות עיבוד בו-זמנית.
- קצב העברת נתונים של החיבור: מספר החיבורים שהופעלו על ידי הלקוחות בכל שנייה. לרוב השירותים שמשתמשים ב-Transport Layer Security (TLS) יש תקורה מסוימת של העברת נתונים ברשת ומשא ומתן על TLS שמשויכת לכל חיבור, והיא לא תלויה בעיבוד הבקשה.
מקבילות של חיבורים: מספר חיבורי הלקוח שעברו עיבוד בו-זמנית.
זמן התגובה של הבקשה: משך הזמן הכולל שחלף בין תחילת הבקשה לסיום התגובה.
שיעור השגיאות: באיזו תדירות בקשות גורמות לשגיאות, כמו שגיאות HTTP 5xx וחיבורים שנסגרו לפני הזמן.
כדי להעריך את תקינות השרת בעומס, יכול להיות שגם ייאספו מדדים פנימיים של השירות במסגרת הליך בדיקת העומס:
שימוש במשאבי המערכת: משאבי מערכת, כמו מעבד, זיכרון RAM ונקודות אחיזה (sockets) של קבצים, מבוטאים בדרך כלל באחוזים.
החשיבות של המדדים האלה משתנה בהתאם לאופן ההטמעה של השירות. הביצועים של האפליקציות יורדים, העומס עליהן יורד או שהן קורסות כשהמשאבים שלהן מתכלים. לכן, חשוב מאוד לקבוע את זמינות המשאבים כשהמארח נמצא בעומס כבד.
שימוש במשאבים מוגבלים אחרים: משאבים שאינם משאבי מערכת, שיכולים להתרוקן בעומס, למשל בשכבת האפליקציה.
דוגמאות למשאבים כאלה:
- מאגר מוגבל של תהליכים או תהליכי משנה של עובדים.
- בשרת אפליקציות שמשתמש בשרשורים, מקובל להגביל את מספר השרשורים של העובדים שפועלים בו-זמנית. הגבלת הגודל של מאגר השרשורים שימושית למניעת ניצול יתר של הזיכרון והמעבד, אבל הגדרות ברירת המחדל לרוב מאוד שמרניות. הגדרת מגבלות נמוכות מדי עלולה למנוע שימוש הולם במשאבי המערכת.
- חלק מהשרתים משתמשים במאגרי תהליכים במקום במאגרי שרשורים. לדוגמה, שרת Apache, כשהוא מוגדר עם מודל ריבוי המשימות של Prefork, מקצה תהליך אחד לכל חיבור לקוח. לכן, מגבלת הגודל של המאגר קובעת את הרף העליון של מספר החיבורים בו-זמנית.
- שירות שנפרס כקצה קדמי של שירות אחר שיש לו מאגר חיבורים לבק-אנד בגודל מוגבל.
תכנון קיבולת לעומת בדיקות עומס יתר
כלים לבדיקת עומסים עוזרים לכם למדוד בנפרד מאפייני קנה מידה שונים. לצורך תכנון הקיבולת, צריך לקבוע את סף העומס לביצועים המקובלים בכמה מימדים. לדוגמה, במקום למדוד את המגבלה המוחלטת של בקשת שירות לאורך זמן, כדאי למדוד את הנתונים הבאים:
- קצב הבקשות שבו השירות יכול לפעול עם זמן אחזור באחוזון ה-99 שהוא פחות ממספר מסוים של אלפיות שנייה. המספר הזה נקבע על ידי הסכם רמת השירות (SLO) של השירות.
- קצב הבקשות המקסימלי שלא גורם לניצול משאבי המערכת לחרוג מהרמות האופטימליות. חשוב לזכור שהשימוש האופטימלי משתנה בהתאם לאפליקציה, ויכול להיות שהוא יהיה נמוך משמעותית מ-100%. לדוגמה, אם השימוש המקסימלי בזיכרון הוא 80%, יכול להיות שהאפליקציה תוכל להתמודד עם עליות קלות בעומס טוב יותר מאשר אם השימוש המקסימלי היה 99%.
חשוב להשתמש בתוצאות של בדיקות העומס כדי לקבל החלטות לגבי תכנון הקיבולת, אבל חשוב גם להבין איך שירות מתנהג כשהעומס חורג מהקיבולת. אלה כמה התנהגויות של שרתים שנבדקות לעיתים קרובות באמצעות בדיקות עומס יתר:
הפחתת עומס: כששירות מקבל יותר מדי בקשות או חיבורים נכנסים, הוא יכול להגיב בהאטת כל הבקשות או בדחיית חלק מהבקשות כדי לשמור על ביצועים סבירים בשאר הבקשות. אנחנו ממליצים על הגישה השנייה כדי למנוע מצב של פסק זמן (timeout) בלקוח לפני קבלת תגובה, וכדי להפחית את הסיכון למיצוי משאבים על ידי הפחתת מספר הבקשות המקבילות בשרת.
עמידות בפני מיצוי משאבים: בדרך כלל, שירות לא קורס בגלל מיצוי משאבים, כי קשה לבקשות בהמתנה להתקדם אם השירות קורס. אם לשירות לקצה העורפי יש הרבה מופעים, החוסן של המופעים הבודדים חיוני לזמינות הכוללת של השירות. בזמן שהפעלה של מופע מסוים מתחילה מחדש אחרי קריסה, יכול להיות שמופעים אחרים יחוו עומס גדול יותר, וזה עלול לגרום לקריסה של כמה מופעים ברצף.
הנחיות כלליות לבדיקה
כשמגדירים את תרחישי הבדיקה, כדאי לפעול לפי ההנחיות הבאות.
יצירת בדיקות בקנה מידה קטן
יוצרים בדיקות בקנה מידה קטן כדי למדוד את מגבלות הביצועים של השרת. אם קיבולת השרת גבוהה מדי, יש סיכון שהבדיקה לא תחשוף את מגבלות הביצועים של השירות עצמו, אבל היא עשויה לחשוף צווארי בקבוק במערכות אחרות, כמו המארחים של הלקוח או שכבת הרשת.
כדי לקבל את התוצאות הטובות ביותר, כדאי להשתמש בתרחיש בדיקה שבו נעשה שימוש במכונה וירטואלית (VM) אחת או ב-Pod של Google Kubernetes Engine (GKE) כדי לבדוק את השירות באופן עצמאי. כדי להגיע לטעינה מלאה בשרת, אפשר להשתמש בכמה מכונות וירטואליות, אבל צריך לזכור שהן עלולות לסבך את איסוף נתוני הביצועים.
בחירת דפוסי עומס של לולאה פתוחה
רוב מחוללי העומסים משתמשים בתבנית של לולאה סגורה כדי להגביל את מספר הבקשות בו-זמנית ולדחות בקשות חדשות עד שהבקשות הקודמות יושלמו. אנחנו לא ממליצים על הגישה הזו כי יכול להיות שהלקוחות של השירות בסביבת הייצור לא יציגו התנהגות כזו של הגבלת קצב הבקשות.
לעומת זאת, התבנית של לולאה פתוחה מאפשרת לגנרטורים של עומסים לדמות את עומס הייצור על ידי שליחת בקשות בקצב קבוע, ללא קשר לקצב שבו מגיעות תגובות השרת.
הרצת בדיקות באמצעות מחוללי עומס מומלצים
אנחנו ממליצים על מחוללי העומס הבאים לבדיקת העומס של שירות ה-Backend:
Nighthawk
Nighthawk הוא כלי בקוד פתוח שפותח בתיאום עם פרויקט Envoy. אפשר להשתמש בו כדי ליצור עומס לקוח, להציג מדדים חזותיים ולמדוד את ביצועי השרת ברוב תרחישי בדיקת העומס של שירותי HTTPS.
בדיקת HTTP/1
כדי לבדוק את HTTP/1, משתמשים בפקודה הבאה:
nighthawk_client URI \
--duration DURATION \
--open-loop \
--no-default-failure-predicates \
--protocol http1 \
--request-body-size REQ_BODY_SIZE \
--concurrency CONCURRENCY \
--rps RPS \
--connections CONNECTIONS
מחליפים את מה שכתוב בשדות הבאים:
-
URI: ה-URI להשוואה -
DURATION: משך הבדיקה הכולל בשניות -
REQ_BODY_SIZE: גודל המטען הייעודי (payload) של POST בכל בקשה
CONCURRENCY: המספר הכולל של לולאות אירועים מקבילותהמספר הזה צריך להיות זהה למספר הליבות במכונה הווירטואלית של הלקוח
RPS: קצב הבקשות ליעד לשנייה, לכל לולאת אירועים
CONNECTIONS: מספר החיבורים המקבילים, לכל לולאת אירועים
מקרה לדוגמה:
nighthawk_client http://10.20.30.40:80 \
--duration 600 --open-loop --no-default-failure-predicates \
--protocol http1 --request-body-size 5000 \
--concurrency 16 --rps 500 --connections 200
הפלט של כל הרצת בדיקה מספק היסטוגרמה של זמני האחזור של התגובות. בדוגמה מתוך המסמכים של Nighthawk, אפשר לראות שזמן האחזור באחוזון ה-99 הוא בערך 135 מיקרו-שניות.
Initiation to completion
samples: 9992
mean: 0s 000ms 113us
pstdev: 0s 000ms 061us
Percentile Count Latency
0 1 0s 000ms 077us
0.5 4996 0s 000ms 115us
0.75 7495 0s 000ms 118us
0.8 7998 0s 000ms 118us
0.9 8993 0s 000ms 121us
0.95 9493 0s 000ms 124us
0.990625 9899 0s 000ms 135us
0.999023 9983 0s 000ms 588us
1 9992 0s 004ms 090us
בדיקת HTTP/2
כדי לבדוק את HTTP/2, משתמשים בפקודה הבאה:
nighthawk_client URI \
--duration DURATION \
--open-loop \
--no-default-failure-predicates \
--protocol http2 \
--request-body-size REQ_BODY_SIZE \
--concurrency CONCURRENCY \
--rps RPS \
--max-active-requests MAX_ACTIVE_REQUESTS \
--max-concurrent-streams MAX_CONCURRENT_STREAMS
מחליפים את מה שכתוב בשדות הבאים:
-
URI: ה-URI להשוואה -
DURATION: משך הבדיקה הכולל בשניות -
REQ_BODY_SIZE: גודל המטען הייעודי (payload) של POST בכל בקשה
CONCURRENCY: המספר הכולל של לולאות אירועים מקבילותהמספר הזה צריך להיות זהה למספר הליבות במכונה הווירטואלית של הלקוח
RPS: קצב היעד של בקשות לשנייה לכל לולאת אירועים
MAX_ACTIVE_REQUESTS: המספר המקסימלי של בקשות פעילות בו-זמנית לכל לולאת אירועים
MAX_CONCURRENT_STREAMS: המספר המקסימלי של הזרמים המקבילים שמותרים בכל חיבור HTTP/2
מקרה לדוגמה:
nighthawk_client http://10.20.30.40:80 \
--duration 600 --open-loop --no-default-failure-predicates \
--protocol http2 --request-body-size 5000 \
--concurrency 16 --rps 500 \
--max-active-requests 200 --max-concurrent-streams 1
ab (כלי בנצ'מרק של Apache)
ab
היא חלופה פחות גמישה ל-Nighthawk, אבל היא זמינה כחבילה כמעט בכל הפצות Linux. מומלץ להשתמש ב-ab רק לבדיקות פשוטות ומהירות.
כדי להתקין את ab, משתמשים בפקודה הבאה:
- ב-Debian וב-Ubuntu, מריצים את הפקודה
sudo apt-get install apache2-utils. - בהפצות שמבוססות על RedHat, מריצים את הפקודה
sudo yum install httpd-utils.
אחרי שמתקינים את ab, מריצים אותו באמצעות הפקודה הבאה:
ab -c CONCURRENCY \
-n NUM_REQUESTS \
-t TIMELIMIT \
-p POST_FILE URI
מחליפים את מה שכתוב בשדות הבאים:
-
CONCURRENCY: מספר הבקשות המקבילות לביצוע -
NUM_REQUESTS: מספר הבקשות לביצוע -
TIMELIMIT: מספר השניות המקסימלי להקצאה לבקשות -
POST_FILE: קובץ מקומי שמכיל את מטען ה-payload של HTTP POST -
URI: ה-URI להשוואה
מקרה לדוגמה:
ab -c 200 -n 1000000 -t 600 -p body http://10.20.30.40:80
הפקודה בדוגמה הקודמת שולחת בקשות עם בו-זמניות (concurrency) של 200 (תבנית של לולאה סגורה), ומפסיקה אחרי 1,000,000 (מיליון) בקשות או אחרי 600 שניות של זמן שחלף. הפקודה כוללת גם את התוכן של הקובץ body כמטען ייעודי (payload) של HTTP POST.
הפקודה ab יוצרת היסטוגרמות של זמן האחזור של התגובה, בדומה לאלה של Nighthawk, אבל הרזולוציה שלה מוגבלת למילישניות, במקום למיקרושניות:
Percentage of the requests served within a certain time (ms)
50% 7
66% 7
75% 7
80% 7
90% 92
95% 121
98% 123
99% 127
100% 156 (longest request)