שלום, AWS Lambda! (חלק ב\')

בפוסט הקודם שלום, AWS Lambda! הצגנו את למבדה, ובעיקר כיצד ה main successful flow עובד.
לא הספקנו כמעט ולהיכנס לעומק / להתנהגויות השונות במודל של למבדה.

זה מה שננסה לעשות בפוסט הזה.

The Container Model

כאשר מתבצעת הפעלה (invocation) ראשונה של הפונקציה שלנו, למבדה מפעילה "Container" שבו תרוץ הפונקציה.
מהו ה container הזה? אין תיעוד מדויק, אך מדובר בסופו של דבר בסביבת ההרצה של הפונקציה, ע"פ ה settings שהגדרנו.

הרצת ה container אורכת זמן מסוים, נאמר כ 100-200ms – מה שנקרא cold start.
על הזמן הזה – המשתמש מחויב.

  • אם הפונקציה רצה עשר פעמים בדקה – אזי זו הפעלה אחת לכל גרסה / עותק חדש של פונקציה (הסבר בהמשך). הבדל זניח.
  • אם הפונקציה רצה פעם בעשר דקות, וזמן ה execution שלה קצר – ה cold start עשוי להכפיל את העלויות.

הערה: העניין הכספי כנראה לא יגרום לכם לעזוב את השימוש בלמבדה, מטרת הדיון היא בעיקר להסביר את אופן העבודה של למבדה.

זמן מה לאחר שהפונקציה הופעלה, למבדה תשמור את ה container חי. הזמן המדויק כנראה תלוי בעומס על השרתים של למבדה, אבל הוא יכול לנוע בין שניות ספורות – לעשרות דקות.

בכל הפעלה עוקבת של הפונקציה, למבדה תנסה לעשות שימוש חוזר בקונטיינר קיים. היא לא תעשה שימוש חוזר במקרים הבאים:

  • אין קונטיינר זמין – למשל "הרגו" אותו לא מזמן…
  • הבקשה הגיעה ל Availability Zone A, אבל הקונטיינר נמצא ב Availability Zone אחר.
  • יש מספר הרצות מקביל של הפונקציה: אם מספר ההרצות בשניה עלה מ 10 ל 100, למבדה תתחיל להריץ עוד ועוד קונטיינרים במקביל – עד שהצורך יסופק.
    כלומר: ייתכן ויש כבר 6 קונטיינרים עובדים, אך במקום לחכות שקונטיינר יתפנה – למבדה החליטה להפעיל קונטיינר שביעי.

    • בעת כתיבת הפוסט, אמזון לא תריץ יותר מ 1000 קונטיינרים במקביל – אלא אם ביקשתם.
    • למבדה תקבע את כמות המקביליות כתלות במקור ה event:
      • אם מדובר בהודעות ב Queue (או "stream-based-event") – המקביליות תהיה ע"פ כמות ה shards של queue.
      • כאשר מדובר בקריאות ישירות (למשל HTTP) – המקביליות תהיה מספר הקריאות בשניה * כמה שניות לוקח לפונקציה לרוץ בממוצע.
    • בכל מקרה, למבדה היא לא קסם. גם אם יש spike "מטורף" – אמזון לא תפתח יותר מ 500 קונטיינרים חדשים בדקה. אפשר לקרוא עוד פרטים על המדיניות כאן.
  • סיבה אחרת לא מתועדת / שאני לא מכיר.
זמני ה Cold Start תלויים ב:
  • כמובן: הקוד שלכם. אם אתם משתמשים ב ORM, או ספריות שדורשות אתחול משמעותי – הזמן הזה ישולם ב Cold Start.
  • כמות הזיכרון שהוקצתה לפונקציה (=> CPU). יותר זיכרון – אתחול מהיר יותר.
  • כמות הקוד שנטען ב ZIP, ספריות וכיוצ"ב: פחות קוד – אתחול מהיר יותר.
  • קוד ב node.js ופייטון יאותחל מהר יותר מקוד ג'אווה או #C.
זמני ההרצה של 4 עותקים זהים של פונקצית למבדה. הפונקציה memInfo0 נקראת בצורה תדירה – ולכן כמעט ואינה מושפעת מ cold start, לעומת הפונקציות האחרות שחוות cold start כמעט כל פעם: כלל שהפונקציה תדירה פחות – הסיכוי ל cold start גדל. מקור: New Relic.

למרות החשש האפשרי מ cold start על הביצועים – ההשפעה של ה cold start על משתמש הקצה היא לרוב קטנה למדי. הנה רכיבים טיפוסיים שגם להם אנו ממתינים בהפעלה של פונקציית למבדה:

  • network latency – עוד כ 100ms או יותר (?), אלא אם אתם קוראים לפונקציה באותו ה region – ואז ה latency הוא מילישניות בודדות.
  • זמני הריצה של ה API Gateway – כ 30 עד 150 מילישניות (ע"פ נתונים של New Relic).
    • הקמת חיבור מאובטח (TLS/SSL) – עשוי לארוך עוד 50-200 מילישניות.

דיי פופולארי היום לדבר על טכניקות ל"שמירת ה container חי" והימנעות מ Cold Start.
בשקלול של כל הרכיבים, נראה ש"הימנעות מ Cold Start" היא התעסקות דיי מיותרת – המשקל של הרכיבים האחרים הוא גדול יותר. לפחות, ברוב הגדול של המקרים.

Container reuse

אם לפונקציה שלכם יש קצב הפעלה בינוני עד גבוה, רבות מההפעלות יתרחשו על container קיים.
זה אומר ש:

  • הגדרות "סטטיות" שנעשו מחוץ ל handler function – עדיין תקפות: חיבור לבסיסי נתונים / רדיס וכו'.
  • Cache ששמרתם בזיכרון – עדיין מלא.
  • דברים שנרשמו לדיסק עדיין שם (יש לכם עד חצי ג'יגה אכסון בתיקיה tmp/)
זה פוטנציאל לשיפור ביצועים משמעותי.
כמובן, שלעולם אי אפשר להסתמך על container reuse: אם הוא יצא – אפשר לנצל אותו, אם לא אז לא. עליכם לכתוב את הקוד בהתאם.
כמו כן, חשוב להבין את התנהגות ה cache בצורה נכונה: אם יש מקביליות גבוהה (concurrent invocation), אזי יש כמה  containers שכל אחד עם cache ב state שונה. חשוב לקחת את זה בחשבון. אם חשוב לכם cache אחיד – פשוט השתמשו ברדיס.
Throttling: a process responsible for regulating the rate at which application processing is conducted
מקור: Robyn

Throttling and retries

כאשר יש הרבה יותר בקשות הרצה להפעלה של פונקציות מאשר containers – למבדה תגדיל את מספר ה containers הרצים.
כאשר יש מעט יותר בקשות הרצה להפעלה של פונקציות מאשר containers – למבדה תבצע throttling. כלומר: תמתין עם הבקשה עוד קצת – ואז תפעיל אותה על גבי ה containers הקיימים.

  • עבור מקורות מסוג Queue (רשמית: "stream-based events") – למבדה תבצע retry לעד. עד שהבקשות מטופלות.
  • עבור מקור קריאה אסינכרונית – למבדה תבצע retry בטווח של עד 6 שעות מרגע הקריאה, עם המתנה בין ניסיון לניסיון, מה שאמור ליצר סיכוי נמוך מאוד למצב של הודעה שלא טופלה.
  • עבור קריאות סינכרוניות (ה event source ממתין לתשובה) – למבדה תחזיר לאפליקציה HTTP status code של 429 – ותצפה שהאפליקציה תבצע retry בעצמה.
Throttling הוא מצב תקין וצפוי בלמבדה – מצב שעליכם לקחת בחשבון! הוא יקרה.
פונקציית הלמבדה שלכם כמובן יכולה להחזיר שגיאות. כאלו שחזרו מלבדה עצמה או מהקוד שלכם.
בלמבדה יש הפרדה בין 2 סוגי Exceptions:

  • Synchronous Exception – כזו שתוצאתה חוזרת למי שקרא לפונקציה.
  • Asynchronous Exception – כזו שתוצאתה מגיעה ל cloudwatch. לקוח הפונקציה לא מודע לדבר.
כשאר הפעלה של פונקציה נתקלה ב Synchronous Exception (שנגרמה ע"י הקוד שלכם או ע"י למבדה) – למבדה תבצע retry ע"פ המדיניות הבאה:
  • עבור מקורות מסוג Queue (רשמית: "stream-based events") – למבדה תבצע retry כל עוד ה data מבחינת ה queue הוא בתוקף.
  • עבור מקור קריאה אסינכרונית – למבדה תבצע retry עוד שתי פעמים, בד"כ בהפרש של כדקה, ואז תשלח את ההודעה ל Dead Letter Queue שהוגדר על ידכם על גבי SNS או SQA.
    • ליתר דיוק בדיקות הראו שאכן ב 99% מהפעמים יהיו 2 retries, אבל לעתים רחוקות יהיה רק retry אחד – ולפעמים גם יבוצעו עד שש retries. מקור.
  • עבור קריאות סינכרוניות (ה event source ממתין לתשובה) – הודעת השגיאה תחזור לאפליקציה, ובאחריותה לבצע retries.
חשוב לציין מגבלה שלא כתובה פה: בעת כתיבת הפוסט, ל API Gateway יש timeout קבוע של 30 שניות. אם יש לכם פונקציה שזמן הריצה שלה ארוך יותר – API Gateway יבצע timeout, בכל זאת.
בשלב הזה אתם אמורים להבין כמעט את כל המדדים שמסופקים ב Monitoring של למבדה:

המדד היחידי שלא הוסבר הוא ה iterator age שרלוונטי רק למקורות מסוג stream-based events.
הוא מציין כמה זמן ארך מרגע שפונקציית הלמבדה שלנו קיבלה batch של הודעות, ועד שסיימה לטפל בהודעה האחרונה. כלומר: מה ה latency המרבי של טיפול בהודעות ב batch, שהגיעו ממקור שכזה.

Lambda@Edge

שווה להזכיר את שירות ה Lambda@Edge ששוחרר לאחרונה, שירות המאפשר להריץ פונקציות למבדה (Nodejs בלבד, כרגע) על ה PoPs (כלומר: Point of Presence) של CloudFront.

לאמזון יש כ 14 regions בעולם עליהם אפשר להריץ את כל שירותי ה AWS, אבל יש לה קרוב ל 100 מיקומים בהם יש לה נוכחות – עבור שירות ה CDN שלה, הרי הוא CloudFront.

עבור פעולות פשוטות למדי, אם תוכלו להריץ את הקוד קרוב מאוד ללקוח שלכם – תוכלו לספק לו תשובה מהירה ביותר: ה latency ל"קוד" שלכם עשוי להיות עשרות מילי-שניות, ולא מאות מילי-שינות.
למבדה_על_הקצה (Lambda@Edge) תנהל עבורכם את שכפול הקוד לרחבי העולם – ותדאג שהלקוחות שלכם, יקבלו זמני תגובה משופרים.

את פונקציית הלמבדה_על_הקצה שלכם, אפשר לחבר לארבע נקודות-חיבור שונות בתהליך של cloudfront (בתרשים: החצים הירוקים והכתומים), ולבצע שינוי על המשאב שהתבקש.

מקור: אמזון

כמובן שבשירות כזה מאוד חשוב לספק זמני תגובה מהירים מאוד – מה שלא תמיד מתרחש בצמד למבדה + API Gateway.

ה API Gateway הוא מחוץ לתמונה, יצירת ה HTTP connection עם TLS/SSL – כבר מתבצע ע"י cloudfront, ולכן הרכיב היחידי שעלול לגרום לעיכובים (ולייתר את היתרון שבריצה על PoP) הוא זמן האתחול של ה container של למבדה. לא סתם התחילו ב nodejs כסביבת-ריצה.

ללמבדה_על_הקצה – יש מגבלות משלה (מקסימום 128MB זיכרון, זמני ריצה קצרים יותר, אין גישה לשירותים אחרים של אמזון, וכו')

שירותים נוסח למבדה_על_הקצה כבר היו קיימים (למשל: PubNub Blocks) – אבל לאמזון יש יתרון מובנה מול מתחרים קטנים יותר.

יהיה מעניין!

סיכום

הפוסט הקודם באמת היה מאוד מקדמי / בסיסי – ונראה לי שהצלחנו לסגור את הפער ולספק היכרות מספיק מעמיקה עם שירות הלמבדה – ויחסית בקלילות.

שיהיה בהצלחה!

—-

לינקים רלוונטיים

Lambda@Edge

תקשורת: מיהו התוכי האמיתי של האינטרנט המהיר?

הצחיק אתכם התוכי של בזק שנוסע במרכז ת\"א במסלול משלו?

זו פרסומת טובה. המסר מוחשי ומובן לכולם. בזק מתארת בפרסומים \"רשת נפרדת\", אך לא ברור מה בדיוק היא מספקת בפועל.עד כמה שידוע לי זהו routing מועדף (על בסיס static IP address) ויותר רוחב פס – לא יותר. אין שום רשת פיסית נפרדת – ואם הייתה, היא בוודאי לא הייתה נפרשת לכל קצוות תבל.

בספרי תקשורת האקדמיים האינטרנט מתואר כמערכת ציבורית ושיוויונית של רשתות מקומיות שמחוברות בינהן עם כמה כבלים בעלי נפח תעבורה גבוה במיוחד שמהווים \"קיצורי דרך\" בין צמתי תקשורת מרכזיים.
ובכן, תמונה זו נכונה אך אינה שלמה.

מתברר שיש שירות אינטרנט פרימיום שמספק אינטרנט מהיר וזמין במיוחד לאלו שמוכנים לשלם עבורו. יודעים מה? אפילו סביר שאתם משתמשים בו מבלי לדעת. אם אתם מורידים קבצים ב iTunes, למשל, אתם משתמשים באינטרנט הפרטי והמועדף. החברה שמוכרת את השירות מדברת על קצבים שגבוהים עד פי 20 מהאלטרנטיבה הציבורית וזמינות גבוהה יותר מהרגיל (כאשר באינטרנט הציבורי יש תקלות). מופתעים? מוכנים להתחייב שכרטיס האשראי שלכם לא מחויב על שימוש באינטרנט המועדף?

כנראה שתמונת האינרנט לא תהיה שלמה ללא הכרות עם חברת Akamai.
אקמיי (Akamai) חברה מסחרית היושבת במדינת מסצ\'וסטס (זו שקשה לומר את שמה) אחראית לנתון מדהים של 15 עד 30 אחוז* מתעבורת האינטרנט העולמית!
היא עושה זאת בעזרת 90 אלף שרתים המפוזרים ב 1800 אתרים (נכון למידע העדכני שמצאתי באינטרנט – והמספר רק גדל)
מי שמשלם על השירות הוא חברות האינטרנט שרוצות לספק תוכן מהיר (Apple, CNN, MTV ועוד). הרשת של Akamai אינה רשת פיסית (כמו כל דבר כמעט באינטרנט…) אלא רשת ווירטואלית ומשתמשת בעיקר בטכניקות הבאות:

Caching 
Akamai מבצעת Caching (דינאמי, שעם הזמן יכול להיות העתק של השרת המקורי) של תוכן משרת הלקוח לשרתים רבים ברשת שלה שפזורים בכל רחבי העולם. המשתמש שפונה לאתר הלקוח מופנה (ללא ידיעתו) לשרת הקרוב אליו גאוגרפית של Akamai.
אם התוכי של Akamai לא היה מביא את הסרט שאתם מורידים (אופס, כתבתי את זה?) לישראל או הסביבה – שום תוכי של בזק לא היה משיג 100Mbps בהורדת התוכן.
\"אבל חלק גדול מאוד מדפי האינטרנט הוא דפים דינאמיים\" יטען מפתח האינטרנט. נכון, אבל יש תמונות וקבצי מדיה (וידאו הוא כמעט חצי בכל תעבורת האינטרנט בבתים) שניתן לעשות caching בקלות ויש גם דרכים לבודד אלמנטים מהתוכן הדינאמי שלא משתנים ולשמור אותם ב cache.

Remote Proxy
למי שזוכר קצת תאוריה, יצירת קשר ב tcp (או http) דורשת 3 קריאות IP (הידוע כ three way handshake) ואם רוצים תוכן מאובטח (ssl) – עוד 4 קריאות handshake נוספות. במצב בו כל קריאת http/s מייצרת connection חדש – יעברו 3 או 7 הודעות ברשת בין השרת והלקוח עד שעמוד האינטרנט יתחיל לרדת (= latency). אקמיי יודעת להחזיק connection קבוע בין השרת של הלקוח לשרת המקומי שלה, לתת למשתמש לבצע handshake מול השרת המקומי שלה ומשם להשתמש ב connection קבוע. טכניקה זו פחות נדרשת עם העליה בתמיכה בפרוטוקול http 1.1 שהסדיר את שמירת ה connection הקיים בעזרת keep alive או pipelining. עדיין – פתרון מעורר מחשבה.

Improved Routing
Akamai טוענת שיש לה אלגוריתם גאוני (הרי הוקמה ע\"י בוגרי MIT, שאחד מהם, ישראלי, דני לוין נהרג בפיגועי 9/11  תוך מאבק בחוטפי אחד המטוסים***) ל routing משופר ברחבי האינטרנט, שמגיב גם הרבה יותר מהר לתקלות בתשתית התקשורת העולמית. עם פריסה ב 1800 אתרים ושליטה מרכזית בהם ייתכן שהיא צודקת (למרות שמבחנים הראו רק שיפור קל, בממוצע, על ה routing של האינטרנט עצמו).

Data Compression

יש חברות (CDN (Content Delivery Network אחרות (Akamai היא הגדולה, אך בהחלט לא היחידה) שמבצעות דחיסה יעילה במיוחד של תוכן דינאמי בין שרת הלקוח לשרת המקומי – לשיפור התעבורה. בוודאי יש עוד טכניקות רבות בשימוש…
ספציפית דחיסה נראית לי שיטה שלא תחזיק זמן רב בהתבסס על חוק נילסן: החוק שאומר שאמנם מעבדים מכפילים את כוחם כל 18 חודשים (חוק מור), אך הרשת מכפילה את קצב ההעברה פי 100 כל עשור (שזה יותר) – ולכן מתישהו (אנחנו עדיין מחכים) תשתנה הפרדיגמה ויהיה עדיף להעביר יותר תוכן ברשת בכדי לחסוך cycles של המעבד.

למי שרוצה קצת לחפור יותר, הנה מסמך שמסביר כיצד Akamai עושה את מה שהיא עושה.

העתיד
כיום כבר יש לא מעט חברות CDN, אני מודע לאחת משלנו (קונטנדו הישראלית) והתחרות גוברת. Akamai שהבינה שהיא מאויימת על ידי רשתות P2P לגיטימות שצצו בשנים האחרונות (שהן זולות יותר ובעלות scale פוטנציאלי גדול יותר), התחילה לפעול גם בזירה הזו. Akamai מספקת Download Manager שאמור לשפר מהירות הורדה מאתרים מסוימים, אבל בעצם משתף את ההורדה P2P עם גולשים קרובים גיאוגרפית ששותפים לאותה ההורדה.
מאחר וחברות אבטחה הוסיפו למוצרהם יכולות CDN (דוגמא ישראלית: אינקפסולה**), הלכה Akamai והוסיפה יכולות אבטחה (בסיסיות) לשירותי ה CDN שלה. בזכות מערך השרתים האדיר השלה היא הצליחה לעצור ביולי 2009 התקפת DDoS אימתנית בקצב של 124Gbps על גוף ממשלתי בארה\"ב – קצב שהיה מפיל חברות רבות שנותנות שירותים דומים. בקיצור – נשמע שתהיה פה עוד נגיסה הדדית בין תחום האבטחה לתחום ה CDN.

גילוי נאות: הכותב מועסק בחברת Imperva, חברת האם של חברת אינקפסולה.

עדכון: ניתן למצוא סיכום עברי על דו\"ח מצב האינטרנט של Akamai כאן.


* תלוי ב יום / שעה.

** כצפוי, אינקפסולה מספקת אבטחה חזקה מזו של Akamai, כמו ש Akamai מספקת CDN טוב בהרבה מזה של אינקפסולה.

*** תודה ל Kalen מאתר HWZone על הלינק לוידאו.