לא כתבתי כבר המון זמן: חופש, ילדים, ועניינים שונים - ולאחרונה לא מעט עבודת ייצוב בלתי-צפויה במערכת שלנו.
למה בלתי צפויה?
ובכן, אתחיל במעט רקע: לאחרונה פירקנו מתוך המערכת הראשית שלנו ("המונוליט") כ 7 מיקרו-שירותים חדשים, חלקם קריטיים לפעולה תקינה של המערכת. כל שירות הותקן בסביבה של High Availability עם שניים או שלושה שרתים ב Availability Zones שונים באמזון. חיברנו Monitoring לשירותים - פעולות סטנדרטיות. בהמשך תכננו לפתח את היציבות אפילו יותר, ולהוסיף Circuit Breakers (דפוס עיצוב עליו כתבתי בפוסט קודם) - בכדי להתמודד בצורה יפה יותר עם כשלים חלקיים במערכת.
עד כאן דיי סטנדרטי, טוב ויפה. התכוננו לכך שכל שרת במערכת יכול ליפול בכל רגע, וללא התרעה. אפילו כמה שרתים בו-זמנית.
הבעיה שנתקלנו בה הגיעה מכיוון בלתי-צפוי: משהו שנראה כמו התנהגות חריגה של הרשת.
- "נראה כמו" ?
כן. אנחנו עדיין בודקים את זה עם אמזון. לא הצלחנו לשים אצבע בדיוק על מקור התופעה. אחת לכמה זמן, שירותים מסוימים במערכת חווים תנאי-רשת דיי קיצוניים:
החוויה החריגה הראשונה שנתקלנו בה - היא starvation: בקשות בשירותים השונים הממתינות בתור לקבל CPU (ליתר דיוק: להיות מתוזמנות ל process של ה Application Server - אולי אספר עוד בפוסט נפרד), וממתינות זמן רב - שניות. אותן קריאות שבד"כ מטופלות בעשרות מילי-שניות.
כאשר מוסיפים nodes ל cluster, למשל 50%, 100% או אפילו 200% יותר חומרה - המצב לא משתפר: זמני ההמתנה הארוכים (שניות ארוכות) נותרים, ויש אחוז גבוה של כישלונות.
בדיקה מעמיקה יותר גילתה את הסיבה ל starvation: שירות A מבקש משהו משירות B, אך כ 3% מהקריאות לשירות B לא נענות תוך 10 שניות (להזכיר: זמן תגובה ממוצע הוא עשרות בודדות של מילי-שניות).
תוך זמן קצר, כמעט כל התהליכים עסוקים ב"המתנות ארוכות" לשירות B - והם אינם פנויים לטיפול בעוד בקשות.
כאשר כל טרנזקציה בשירות B מבצעת כ 3 קריאות לשירות A ("מה זה משנה? - הן כ"כ מהירות"), הסבירות ל"תקיעת" הטרנזקציה על timeout עולה מ 1% לכ 3% - כאשר יש כ 1% התנתקויות של connections.
מדוע "המזל הרע" הזה? מדוע רובים של התהליכים דווקא עסוקים ב"המתנות ארוכות"?
התשובה היא הסתברותית: הם הצליחו לענות במהירות לכמה עשרות קריאות בהן הייתה המתנה קצרה (התנהגות רגילה) - ואז הגיעו ל"המתנה הארוכה" שלהם, אורכה של "המתנה ארוכה" היא כאורך טיפול כב 100-500 קריאות מהירות (תלוי ב endpoint הספציפי).
התוצאה הסופית היא זמני-תגובה בלתי-סבירים של המערכת: חלקים האחד בשל המתנה ל timeout של 10 שניות (שהייתה ברירת המחדל אצלנו, כשעלינו לאוויר), ואחרים בשל מיעט התהליכים שנותרו לטיפול בכל הקריאות האחרות.
הפעולה המידית הייתה:
הסיפור הוא עוד ארוך ומעניין, אך אתמקד בעיקרי הדברים:
הקרבה של כ 1% מהבקשות הוא עדיין קשה מנשוא, ולכן אפרט את המנגנון שהתאמנו לבעיה.
זו דוגמה נפלאה כיצד דפוס העיצוב המקובל (למשל: Circuit Breaker) הוא כמעט חסר חשיבות - למקרה ספציפי שלנו (הכישלונות הם לא של השרת המרוחק - אלא בדרך הגישה אליו). אם היינו מחברים circuit breakers בכל נקודה במערכת - לא היינו פותרים את הבעיה, על אף השימוש ב "דפוס עיצוב מקובל ל Fault-Tolerance".
המנגנון שהרכבנו, בנוי מכמה שכבות:
אני מבהיר זאת שוב: Timeouts ללא Fallback או Retries זו בעצם הקרבה של ה traffic. היא יותר טובה מכלום, במצבים מסוימים - אך זו איננה התנהגות רצויה כאשר מדובר בקריאות שחשובות למערכת.
בגדול מאוד, בכל קריאה מרוחק - הוספנו מנגנון שמתנהג בערך כך:
===================================================
אני מדלג מעט קדימה... ומוסיף את שני המרכיבים הנוספים למנגנון:
תהליך זה מתרחש לכל Endpoint משמעותי, כאשר יש לעשות fine-tune ל endpoints השונים.
שימו לב להדרגה שנדרשת ב timeouts: אם שירות A קורא לשירות B שקורא לשירות C - ולכל הקריאות יש timeout של 2000 מילי-שניות, כל timeout בין B ל C --> יגרור בהכרח timeout בין A ו B, אפילו אם ל B היה fallback מוצלח לחוסר התשובה של C.
בגלל שכל קריאה ברשת מוסיפה כ 1-3 מילי-שניות, ה timeouts צריכים ללכת ולהתקצר ככל שאנו מתקדמים בקריאות.
ה retry - מסבך שוב את העניין.
כרגע אנחנו משחקים עם קונפיגורציה ידנית שהיא הדרגתית (cascading), קרי: ה timeout בקריאה C <-- B תמיד יהיה קצר מה timeout בקריאה בין B <-- A.
אחד הרעיונות שאני כרגע משתעשע בהם הוא להעביר "SLA לזמן תגובה" כפרמטר בקריאה ל endpoint. כלומר: לומר לשירות "יש לך 1980 מילי-שניות לענות לבקשה, או שאני מתעלם ממנה". משהו נוסח "הודעה זו תשמיד את עצמה בתוך 20 שניות" של סדרת סרטי "משימה בלתי-אפשרית".
באופן זה השירות שמקבל את הבקשה יוכל באופן מושכל לחלק את הזמן שניתן לו בין ה endpoint מהם הוא זקוק לתשובה, או שאולי אפילו יחליט לעובר ל fallback ישר - מחוסר זמן. זה פשוט... ומסובך - באותו הזמן.
כמובן שאת כל המנגנון יעטוף גם Circuit Breaker - זה קצת פחות דחוף עכשיו....
באופן צפוי, כישלונות של מערכת מגיעים (גם) במקומות שלא צפינו אותם: אנו לוקחים את הסיכונים בחשבון, בונים מנגנוני-הגנה, ונתקלים בבעיות אחרות שלא התכוננו אליהן.
מה שחשוב הוא להבין מה הבעיה - ולפתור אותה. לא לפתור את הבעיות שהיו ל Amazon, נטפליקס או SoundCloud.
באופן דומה, אני ממליץ לכם לא לרוץ ולממש את המנגנון שתיארתי - אלא אם אתם נתקלים בהתנהגות דומה.
אם למישהו מכם, יש ניסיון בהתמודדות דומה - אשמח לשוחח על כך. אנא כתבו לי הודעה או שלחו לי מייל (liorb [at] gett.com) ואשמח להחליף תובנות.
מנגנון העברת-ידע חשוב שלנו, בני-האדם, מבוסס על סיפורים. קל לנו לזכור סיפור ולקשר אותם לאירועים.
אני מקווה שהסיפור שאנו חווינו יהיה מעניין עבורכם, ואולי יוכל לתת לכם קשר לדברים אחרים שאתם תזדקקו להם.
שיהיה בהצלחה!
---
לינקים רלוונטיים:
AWS Noiseness
למה בלתי צפויה?
ובכן, אתחיל במעט רקע: לאחרונה פירקנו מתוך המערכת הראשית שלנו ("המונוליט") כ 7 מיקרו-שירותים חדשים, חלקם קריטיים לפעולה תקינה של המערכת. כל שירות הותקן בסביבה של High Availability עם שניים או שלושה שרתים ב Availability Zones שונים באמזון. חיברנו Monitoring לשירותים - פעולות סטנדרטיות. בהמשך תכננו לפתח את היציבות אפילו יותר, ולהוסיף Circuit Breakers (דפוס עיצוב עליו כתבתי בפוסט קודם) - בכדי להתמודד בצורה יפה יותר עם כשלים חלקיים במערכת.
עד כאן דיי סטנדרטי, טוב ויפה. התכוננו לכך שכל שרת במערכת יכול ליפול בכל רגע, וללא התרעה. אפילו כמה שרתים בו-זמנית.
הבעיה שנתקלנו בה הגיעה מכיוון בלתי-צפוי: משהו שנראה כמו התנהגות חריגה של הרשת.
- "נראה כמו" ?
כן. אנחנו עדיין בודקים את זה עם אמזון. לא הצלחנו לשים אצבע בדיוק על מקור התופעה. אחת לכמה זמן, שירותים מסוימים במערכת חווים תנאי-רשת דיי קיצוניים:
- Latency בתוך ה Data Center (בין AZs) שקופץ מ 2 מילי-שניות בממוצע לכ 80 מילי-שניות בממוצע. 80 מילי-שניות הוא הממוצע, אבל גם לא נדיר להיתקל ב latency של 500 מילי-שניות - כאילו השרת נמצא ביבשת אפריקה (ולא ממש ב Data Center צמוד, עם קווי תקשורת dedicated).
- גלים של אי-יציבות, בהם אנו חווים אחוז גבוה מאוד של timeouts (קריאות שלא נענות בזמן סביר), במקרים הקיצוניים: יותר מ 1% מניסיונות ה tcp connections שאנו מבצעים - נכשלים (בצורת timeout - לאחר זמן מה).
אנחנו רגילים לתקשורת-לא מושלמת בסביבה של אמזון - אבל זה הרבה יותר ממה שהיינו רגילים אליו עד עתה. בניגוד לעבר - אנו מתנסים לראשונה בכמות גדולה של קריאות סינכרוניות שהן גם קריטיות למערכת (כמה אלפי קריאות בדקה - סה"כ).
זה נקרא "ענן" - אבל ההתנהגות שאנו חווינו דומה הרבה יותר ללב-ים: לעתים שקט ונוח - אבל כשיש סערה, הטלטלה היא גדולה. מקור: http://wallpoper.com/ |
סימני הסערה
החוויה החריגה הראשונה שנתקלנו בה - היא starvation: בקשות בשירותים השונים הממתינות בתור לקבל CPU (ליתר דיוק: להיות מתוזמנות ל process של ה Application Server - אולי אספר עוד בפוסט נפרד), וממתינות זמן רב - שניות. אותן קריאות שבד"כ מטופלות בעשרות מילי-שניות.
כאשר מוסיפים nodes ל cluster, למשל 50%, 100% או אפילו 200% יותר חומרה - המצב לא משתפר: זמני ההמתנה הארוכים (שניות ארוכות) נותרים, ויש אחוז גבוה של כישלונות.
בדיקה מעמיקה יותר גילתה את הסיבה ל starvation: שירות A מבקש משהו משירות B, אך כ 3% מהקריאות לשירות B לא נענות תוך 10 שניות (להזכיר: זמן תגובה ממוצע הוא עשרות בודדות של מילי-שניות).
תוך זמן קצר, כמעט כל התהליכים עסוקים ב"המתנות ארוכות" לשירות B - והם אינם פנויים לטיפול בעוד בקשות.
כאשר כל טרנזקציה בשירות B מבצעת כ 3 קריאות לשירות A ("מה זה משנה? - הן כ"כ מהירות"), הסבירות ל"תקיעת" הטרנזקציה על timeout עולה מ 1% לכ 3% - כאשר יש כ 1% התנתקויות של connections.
מדוע "המזל הרע" הזה? מדוע רובים של התהליכים דווקא עסוקים ב"המתנות ארוכות"?
התשובה היא הסתברותית: הם הצליחו לענות במהירות לכמה עשרות קריאות בהן הייתה המתנה קצרה (התנהגות רגילה) - ואז הגיעו ל"המתנה הארוכה" שלהם, אורכה של "המתנה ארוכה" היא כאורך טיפול כב 100-500 קריאות מהירות (תלוי ב endpoint הספציפי).
התוצאה הסופית היא זמני-תגובה בלתי-סבירים של המערכת: חלקים האחד בשל המתנה ל timeout של 10 שניות (שהייתה ברירת המחדל אצלנו, כשעלינו לאוויר), ואחרים בשל מיעט התהליכים שנותרו לטיפול בכל הקריאות האחרות.
הפעולה המידית הייתה:
- הפחתת ה timeouts ל-2 שניות, במקום 10 שניות. הקשר: השירות הכי אטי שלנו עונה ב 95% מהקריאות, גם בשעות עומס - בפחות מ 500 מילי-שניות.
- צמצום מספר הקריאות בין השירותים: בעזרת caches קצרים מאוד (כ 15 שניות) או בעזרת קריאות bulk. למשל: היה לנו שירות D שבכל טרנזקציה ביצע 12 קריאות לשירות E, למה? - חוסר תשומת לב. שינוי הקוד לקריאת bulk לא הפך את הקוד למסורבל.
בעצם ריבוי הקריאות, השירות בעצם הכפיל את הסיכוי שלו בפי-12, להיתקע על timeout כלשהו. קריאה אחת שמטפלת ב 12 הבקשות היא יעילה יותר באופן כללי, אך גם מצמצת את סבירות ההתקלויות ב timeouts.
בכל מקרה: קריאה שלא נענתה בזמן סביר - היא כבר לא רלוונטית.
המשך הפתרון
הסיפור הוא עוד ארוך ומעניין, אך אתמקד בעיקרי הדברים:
- באופן פרדוקסלי, השימוש ב timeouts (כישלון מהיר) - מעלה את רמת היציבות של המערכת.
- השימוש ב timeouts + צמצום מספר הקריאות המרוחקות, כמו שהיה במקרה שלנו, בעצם מקריב כ 1% מהבקשות (קיצרנו את ההמתנה ל-2 שניות, אך לא סיפקנו תשובה מלבד הודעת שגיאה) - על מנת להציל את 99% הבקשות האחרות, בזמני סערה (אין ל timeout השפעה כאשר הכל מתנהג כרגיל).
הקרבה של כ 1% מהבקשות הוא עדיין קשה מנשוא, ולכן אפרט את המנגנון שהתאמנו לבעיה.
זו דוגמה נפלאה כיצד דפוס העיצוב המקובל (למשל: Circuit Breaker) הוא כמעט חסר חשיבות - למקרה ספציפי שלנו (הכישלונות הם לא של השרת המרוחק - אלא בדרך הגישה אליו). אם היינו מחברים circuit breakers בכל נקודה במערכת - לא היינו פותרים את הבעיה, על אף השימוש ב "דפוס עיצוב מקובל ל Fault-Tolerance".
המנגנון שהרכבנו, בנוי מכמה שכבות:
- Timeouts - על מנת להגן על המערכת בפני starvation (ומשם: cascading failures).
- Retries - ביצוע ניסיון תקשורת נוסף לשירות מרוחק, במידה וה connection התנתק.
- Fallback (פונקציה נקודתית לכל endpoint מרוחק) - המספקת התנהגות ברירת מחדל במידה ולא הצלחנו, גם ב retry - לקבל תשובה מהשירות המרוחק.
- Logging and Monitoring - שיעזרו לנו לעשות fine-tune לכל הפרמטרים של הפתרון. ה fine-tuning מוכיח את עצמו כחשוב ביותר.
- Circuit Breakers - המנגנון שיעזור לנו להגיע ל Fallbacks מהר יותר, במידה ושרת מרוחק כשל כליל (לא המצב שכרגע מפריע לנו).
אני מבהיר זאת שוב: Timeouts ללא Fallback או Retries זו בעצם הקרבה של ה traffic. היא יותר טובה מכלום, במצבים מסוימים - אך זו איננה התנהגות רצויה כאשר מדובר בקריאות שחשובות למערכת.
בגדול מאוד, בכל קריאה מרוחק - הוספנו מנגנון שמתנהג בערך כך:
===================================================
- בצע קריאה מרוחקת (עם timeout של עד 2000 מילי-שניות, בד"כ פחות).
- אם הקריאה הצליחה - שמור אותה ב fallback cache (הסבר - מיד).
- אם היה timeout - ספק תשובה מתוך ה fallback cache (פשרה).
===================================================
חשוב להבהיר: ה Fallback cache הוא Cache נפרד מ Cache רגיל (אם יש כזה). הוא ארוך טווח (כרגע: אנו מנסים 24 שעות), ולעתים הוא שומר מידע פחות ספציפי - כדי שיישאר נהיל ולא יהיה גדול מדי.
ע"פ המדידות שלנו, בזמנים טובים רק כ 1 מ 20,000 או 25,000 קריאות תגיע ל fallback - כלומר משתמש אחד מקבל תשובה שהיא פשרה (degraded service).
בזמני סערה, אחוז הקריאות שמגיעת מתוך ה fallback מגיע ל 1 מ 500 עד 1 ל 80 (די גרוע!) - ואז הפשרה היא התנהגות משמעותית.
באחוזים שכאלו - הסיכוי שבקשה לא תהיה ב fallback cache היא סבירה (מאוד תלוי בשירות, אבל 10% הוא לא מספר מופרך). למקרים כאלו יש לנו גם התנהגות fallback סינתטית - שאינה תלויה ב cache.
מצב ברור שבו אין cache - כאשר אנו מעלים מכונה חדשה. ה caches שלנו, כיום, הם per-מכונה - ולא per-cluster ע"מ לא להסתמך על קריאות רשת בזמן סערה. למשל: יש לנו שירות אחד שניסינו cache מבוזר של רדיס. זה עובד מצוין (גם ביצועים, ו hit ratio מוצלח יותר) - עד שפעם אחת זה לא עבד מצוין.... (והמבין יבין).
כלומר, המנגנון בפועל נראה דומה יותר לכך:
===================================================
ע"פ המדידות שלנו, בזמנים טובים רק כ 1 מ 20,000 או 25,000 קריאות תגיע ל fallback - כלומר משתמש אחד מקבל תשובה שהיא פשרה (degraded service).
בזמני סערה, אחוז הקריאות שמגיעת מתוך ה fallback מגיע ל 1 מ 500 עד 1 ל 80 (די גרוע!) - ואז הפשרה היא התנהגות משמעותית.
באחוזים שכאלו - הסיכוי שבקשה לא תהיה ב fallback cache היא סבירה (מאוד תלוי בשירות, אבל 10% הוא לא מספר מופרך). למקרים כאלו יש לנו גם התנהגות fallback סינתטית - שאינה תלויה ב cache.
מצב ברור שבו אין cache - כאשר אנו מעלים מכונה חדשה. ה caches שלנו, כיום, הם per-מכונה - ולא per-cluster ע"מ לא להסתמך על קריאות רשת בזמן סערה. למשל: יש לנו שירות אחד שניסינו cache מבוזר של רדיס. זה עובד מצוין (גם ביצועים, ו hit ratio מוצלח יותר) - עד שפעם אחת זה לא עבד מצוין.... (והמבין יבין).
כלומר, המנגנון בפועל נראה דומה יותר לכך:
===================================================
- בצע קריאה מרוחקת (עם timeout של עד 2000 מילי-שניות, בד"כ פחות).
- אם הקריאה הצליחה - שמור אותה ב fallback cache (הסבר מייד).
- אם היה timeout - ספק תשובה מתוך ה fallback cache (פשרה), או שתספק fallback סינתטי.
===================================================
איך מגדירים fallback סינתטי? זה לא-פשוט, ותלוי מאוד בתסריט הספציפי. כקו-מנחה יש לחשוב על:
- ערכי ברירת-מחדל טובים.
- התנהגות שתמנע מפיצ'רים פחות חשובים לעבוד (למשל: לא להציג pop-up פרסומי למשתמש - אם אין מספיק נתונים להציג אותו יפה)
- להניח שהמצב שאנו לא יודעים לגביו - אכן מתרחש (כן... המונית עדיין בדרך).
- להניח שהמצב שאנו לא יודעים לגביו - התרחש בצורה הרעה ביותר (למשל: לא הצלחנו לחייב על הנסיעה)
- אפשרות: הציגו הודעת שגיאה נעימה למשתמש ובקשו ממנו לנסות שוב. המשתמש לרוב מגיב בטווח של כמה שניות - זמן ארוך כ"כ (בזמני-מחשב), שמספר דברים עשויים להשתנות לטובה במצב ה caches / הידע שלנו בפרק זמן שכזה.
תמונה מלאה יותר
אני מדלג מעט קדימה... ומוסיף את שני המרכיבים הנוספים למנגנון:
כיוון שהבעיות הן בעיות של אקראיות (כמעט) - ל retry יש סיכוי גדול לעזור.
גילינו למשל, תוך כדי ניסיונות ו tuning את הדבר הבא: רוב הכישלונות שאנו חווים הם ברמת יצירת ה connection ("לחיצת-יד משולשת") והרבה פחות בעת קריאת נתונים ברשת.
עוד דבר שגילינו, הוא שלמרות שהצלחות בפתיחת connection מתרחשות ב 99.85% בפחות מ-3 מילי-שניות, הניסיון לעשות retry לפתיחת connection מחדש לאחר כ 5 מילי-שניות - כמעט ולא שיפר דבר. לעומת-זאת, ניסיון retry לפתיחת connection מחדש לאחר כ 30 מילי-שניות עשה פלאים - וברוב הגדול של הפעמים הסתיים ב connection "בריא".
האם מדובר בסערה שאיננה אקראית לחלוטין, או שיש לכך איזה הסבר מושכל שתלוי בסביבת הריצה (AWS, וירטואליזציה, וכו')? קשה לומר - לא חקרנו את העניין לשורש. נסתפק בכך כ retry לאחר 30 מילי-שניות - משפר את מצבנו בצורה משמעותית.
עניין חשוב לשים לב אליו הוא שעושים קריאות חוזרות (retry) רק ל APIs שהם Idempotent, כלומר: לא יהיה שום נזק אם נקרא להם פעמיים. (שליפת נתונים - כן, חיוב כרטיס אשראי - לא).
שימוש ב Cache קצר-טווח הוא עדיין ואלידי ונכון
כל עוד לא מערבבים אותו עם ה fallback cache.
מכאן התוצאה היא:
===================================================
- בצע קריאה מרוחקת
- נסה קודם לקחת מה cache הרגיל
- אם אין - בצע קריאה מרוחקת (עם timeout של עד 2000 מילי-שניות לקריאה, בד"כ פחות + timeout של 30ms ליצירת connection).
- אם היה timeout + במידת האפשר - בצע קריאה שנייה = retry.
- אם הקריאה הצליחה - שמור אותה ב fallback cache.
- אם לא הצלחנו לספק תשובה - ספק תשובה מתוך ה fallback cache (פשרה), או שתספק fallback סינטתי.
- ספק למשתמש חווית-שימוש הטובה ביותר למצב הנתון. חוויה זו ספציפית לכל מקרה.
===================================================
תהליך זה מתרחש לכל Endpoint משמעותי, כאשר יש לעשות fine-tune ל endpoints השונים.
שימו לב להדרגה שנדרשת ב timeouts: אם שירות A קורא לשירות B שקורא לשירות C - ולכל הקריאות יש timeout של 2000 מילי-שניות, כל timeout בין B ל C --> יגרור בהכרח timeout בין A ו B, אפילו אם ל B היה fallback מוצלח לחוסר התשובה של C.
בגלל שכל קריאה ברשת מוסיפה כ 1-3 מילי-שניות, ה timeouts צריכים ללכת ולהתקצר ככל שאנו מתקדמים בקריאות.
ה retry - מסבך שוב את העניין.
כרגע אנחנו משחקים עם קונפיגורציה ידנית שהיא הדרגתית (cascading), קרי: ה timeout בקריאה C <-- B תמיד יהיה קצר מה timeout בקריאה בין B <-- A.
אחד הרעיונות שאני כרגע משתעשע בהם הוא להעביר "SLA לזמן תגובה" כפרמטר בקריאה ל endpoint. כלומר: לומר לשירות "יש לך 1980 מילי-שניות לענות לבקשה, או שאני מתעלם ממנה". משהו נוסח "הודעה זו תשמיד את עצמה בתוך 20 שניות" של סדרת סרטי "משימה בלתי-אפשרית".
באופן זה השירות שמקבל את הבקשה יוכל באופן מושכל לחלק את הזמן שניתן לו בין ה endpoint מהם הוא זקוק לתשובה, או שאולי אפילו יחליט לעובר ל fallback ישר - מחוסר זמן. זה פשוט... ומסובך - באותו הזמן.
כמובן שאת כל המנגנון יעטוף גם Circuit Breaker - זה קצת פחות דחוף עכשיו....
כך נראתה השמדה-עצמית בשנות השמונים. מקור: http://tvtropes.org/ |
סיכום
באופן צפוי, כישלונות של מערכת מגיעים (גם) במקומות שלא צפינו אותם: אנו לוקחים את הסיכונים בחשבון, בונים מנגנוני-הגנה, ונתקלים בבעיות אחרות שלא התכוננו אליהן.
מה שחשוב הוא להבין מה הבעיה - ולפתור אותה. לא לפתור את הבעיות שהיו ל Amazon, נטפליקס או SoundCloud.
באופן דומה, אני ממליץ לכם לא לרוץ ולממש את המנגנון שתיארתי - אלא אם אתם נתקלים בהתנהגות דומה.
אם למישהו מכם, יש ניסיון בהתמודדות דומה - אשמח לשוחח על כך. אנא כתבו לי הודעה או שלחו לי מייל (liorb [at] gett.com) ואשמח להחליף תובנות.
מנגנון העברת-ידע חשוב שלנו, בני-האדם, מבוסס על סיפורים. קל לנו לזכור סיפור ולקשר אותם לאירועים.
אני מקווה שהסיפור שאנו חווינו יהיה מעניין עבורכם, ואולי יוכל לתת לכם קשר לדברים אחרים שאתם תזדקקו להם.
שיהיה בהצלחה!
---
לינקים רלוונטיים:
AWS Noiseness
חומר זהב!
השבמחקשומר בצד ליום סגריר כשנגיע לבעיות דומות.
תודה רבה!