מה זה Health Check Endpoint ולמה כל שרות צריך אחד¶
תארו לעצמכם מסעדה שבה המלצר ממשיך לקחת הזמנות מלקוחות, אבל המטבח כבר תפוס לגמרי או שהתקלקל לו התנור. הלקוחות מזמינים, מחכים, ובסוף לא מקבלים כלום. בדיוק את זה עושה שרת בלי Health Check - הוא ממשיך "לחייך" ולקבל בקשות גם כשהוא כבר לא באמת מתפקד. Health Check Endpoint הוא הדרך של השרת להגיד בכנות "אני בסדר" או "אני לא בסדר", ולמערכות סביבו יש דרך פשוטה לבדוק את זה כל הזמן.
מה זה בעצם Health Check¶
בפועל זה פשוט מאוד - נתיב HTTP קטן, לרוב עם שם כמו health/ או healthz/, שכשמישהו שולח אליו בקשה, השרת עונה במהירות עם קוד סטטוס שאומר אם הכל תקין. תשובה חיובית, ולפעמים גם מידע נוסף על מצב הרכיבים הפנימיים, ותשובת שגיאה אם משהו לא כשורה.
מה שהופך את זה לחשוב הוא לא הקוד עצמו, אלא מי שקורא לו. זה לא נועד לבני אדם שגולשים באתר, אלא למערכות אוטומטיות - load balancer, מערכת ניטור, או מנגנון תזמור קונטיינרים - שקוראות לנתיב הזה שוב ושוב, בלי הפסקה, כדי לדעת בזמן אמת אם השרת הזה כשיר לקבל תנועה.
Liveness מול Readiness - שני סוגי בדיקות¶
כאן יש נקודה חשובה שהרבה מפתחים מפספסים בהתחלה - יש בעצם שני סוגים שונים של בדיקת בריאות, שעונים על שאלות שונות לגמרי.
בדיקת Liveness שואלת שאלה בסיסית מאוד - "האם התהליך הזה בכלל חי ומגיב?". אם התהליך נתקע, קרס פנימית, או נכנס ללולאה אינסופית שממנה הוא לא חוזר, בדיקת ה-Liveness תיכשל. התוצאה של כישלון כאן היא בדרך כלל דרסטית - המערכת שמנטרת מחליטה שהתהליך תקוע ומחליטה להרוג אותו ולהפעיל אותו מחדש, בתקווה שאתחול פשוט יפתור את הבעיה.
בדיקת Readiness שואלת שאלה עדינה יותר - "האם המופע הזה מוכן כרגע להגיש תנועה אמיתית?". יכול להיות מצב שהתהליך חי לגמרי ומגיב, אבל עדיין לא מוכן - למשל ברגעים הראשונים אחרי עלייה, לפני שהוא הספיק להתחבר למסד הנתונים או לטעון קונפיגורציה. במקרה כזה, אין סיבה להרוג את התהליך, פשוט לא כדאי לשלוח אליו תנועה עדיין. אם בדיקת Readiness נכשלת, המערכת פשוט מוציאה זמנית את המופע הזה מרשימת השרתים שמקבלים בקשות, עד שהוא יחזור להיות מוכן.
איך Load Balancer ו-Kubernetes משתמשים בזה¶
בהקשר הפשוט ביותר, load balancer שיושב מול כמה מופעים של השרת שלכם קורא לנתיב ה-health check של כל מופע במרווחים קבועים. מופע שלא עונה או עונה בשגיאה פשוט יורד זמנית מרשימת היעדים שהתנועה מופנית אליהם, ומקבל הזדמנות לחזור ברגע שהוא שוב עונה בחיוב.
במערכות תזמור קונטיינרים כמו Kubernetes הרעיון דומה אבל מתוחכם יותר - המערכת מגדירה עבור כל שירות גם בדיקת Liveness וגם בדיקת Readiness בנפרד, ומשתמשת בהן להחלטות שונות כמו שתיארנו למעלה. לא צריך להבין את כל הפרטים הטכניים של Kubernetes כדי להבין את העיקרון - מספיק לזכור שמערכות תזמור מודרניות בנויות מהיסוד סביב ההנחה שלכל שירות יש נתיב שאפשר לשאול אותו "מה שלומך" ולקבל תשובה אמינה.
מה כדאי לבדוק ומה לא¶
הפיתוי הראשון של מפתחים רבים הוא לעשות מה-health check בדיקה יסודית ומקיפה - לבדוק את החיבור למסד הנתונים, לשירותים חיצוניים, לתור ההודעות, לכל דבר. יש בזה היגיון, כי אם השירות לא יכול להגיע לתלות קריטית, הוא באמת לא באמת "בריא". אבל צריך להיזהר - בדיקה כבדה מדי, שרצה כל כמה שניות על כל מופע, יכולה בעצמה להפוך לעומס משמעותי על מסד הנתונים או על השירותים החיצוניים.
כלל אצבע טוב הוא לבדוק רק תלויות קריטיות באמת, שבלעדיהן השירות לא יכול לתפקד בכלל, ולהשאיר בדיקות עומק יותר יסודיות למערכות ניטור נפרדות שרצות בתדירות נמוכה יותר. כשבונים שירותי צד שרת אמיתיים, ההחלטה הזו על מה נכנס לבדיקת הבריאות היא חלק בלתי נפרד מתכנון ארכיטקטורת השירות, ובקורס צד שרת אנחנו נוגעים גם בהיבטים האלה של הרצת שירות אמין בסביבת פרודקשן.
לסיכום¶
Health Check Endpoint הוא אחד מאותם דברים קטנים שקל לדחות "לפעם הבאה", אבל הוא בעצם הבסיס לכל מנגנון אוטומטי שמנסה לשמור על השירות שלכם למעלה - מ-load balancer פשוט ועד מערכת תזמור מתוחכמת. ההבחנה בין Liveness ל-Readiness היא ההבדל בין "תהרוג ותפעיל מחדש" ל"פשוט אל תשלח לו תנועה כרגע", ושתיהן חשובות.
יש לכם שאלה על איך להגדיר health check לשירות שלכם? בואו לדבר על זה בדיסקורד.