כשאתה אומר "Event-Driven Architecture", למה אתה מתכוון?

אחד הכנסים האהובים עלי, שאני נוהג לעקוב אחרי התוכן שמוצג בו הוא כנס ;goto

ה Keynote ב Goto Chicago שהתקיים לפני מספר ימים היה של מרטין פאוולר, בו הוא ביצע סיווג של סגנונות של \”Event-Driven Architecture\” (או בקיצור: EDA).

יש לי באופן אישי בעיה עם ההגדרה \”Event-Driven Architecture\”.

  • האם הארכיטקטורה עצמה מונעת על ידי אירועים?
  • האם באמת הפרט החשוב ביותר בארכיטקטורה הוא האירועים או כיצד הם מטופלים?

לומר ש \”יש לנו ארכיטקטורה שהיא Event-Driven\” זה כמעט כמו לומר \”יש לנו ארכיטקטורה שהיא Database Driven\” או \”ארכיטקטורה שהיא Java Driven\”. כלומר:

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

בכלל, ככל שמערכת גדלה, ובמיוחד כאשר היא נעשית מבוזרת – יותר סביר שנשתמש באירועים איפשהו במערכת. האם זה הופך את המערכת שלנו ל Event-Driven?

ובכן… מדוע אנשים מציינים שיש להם \”Event Driven Architecture\”? כנראה כי:
א. זה נשמע \”טוב\”. באזז מרשים.
ב. כי אותם אנשים מרוצים מהשימוש ב events – ונתונים לתכונה הזו של המערכת דגש מיוחד.

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

הייתי קורא למערכת כזו \”Event Based\”, ומנסה להבין מה מניע את המערכת והארכיטקטורה שלה. האם מדובר ב Scalability? האם חלוקה של תהליך עיבוד ליחידות קטנות ופשוטות יותר?

אז למה באמת מתכוונים ב \”Event-Driven Architecture\”?

אם נחפש קצת בספרות מקצועית, נוכל למצוא הגדרות כמו זו:
מתוך הספר Event-Driven Architecture: How SOA Enables the Real-Time Enterprise
אני לא רוצה להיות מרושע, אבל באמת זו חתיכת פסקה ארוכה שלא אומרת הרבה…
בספרון של מארק ריצ\’רדס בשם Software Architecture Patterns הוא מתאר שני סוגים עיקריים של EDA:
  • Mediator Topology – בה יש \”מח\” מרכזי שיודע איזה שלבים יש לכל event, אלו ניתן למקבל וכו\’- והוא זה שמנהל אותם
  • Broker Topology – בה החוכמה היא \”מבוזרת\” וכל רכיב שמטפל ב event יודע מה היעד הבא של ה Event / או אילו events חדשים יש לשלוח.
הוא בוחן את נקודות החוזק והחולשה בכל גישה – וזה נחמד, אך הוא עדיין לא ממש מספק תמונה שמכסה את השימושיים העיקריים של events במערכות תוכנה.

קצת עזרה??

כאן באמת הסשן של פאוולר היה מוצלח, ולכן החלטתי שהוא שווה פוסט. פאוולר הוא אולי לא המתכנת המבריק ביותר, אולי לא הארכיטקט הראשון לתכנון מערכות – אבל קשה לי לחשוב על דמות טכנולוגית שיודעת לקחת חומר טכני ולהנגיש אותה לקהל – בצורה טובה כמוהו.
פאוולר מגדיר ארבעה צורות עיקריות לשימוש ב Events במערכת. אם נשתמש במונחים הללו, ולא במונח הכללי \”Event-Driven Architecture\” – הרי נוכל להבין טוב יותר אחד את השני.
Event Notification

זה המקרה הפשוט בו אני רוצה להעביר הודעה בין מודול א\’ למודול ב\’ בצורה אסינכרונית.

למשל: 
  1. אפליקציית הנהג מודיעה שהסיעה הסתיימה.
  2. המערכת לניהול נסיעות סוגרת את הנסיעה ושולחת הודעה שהנסיעה הסתיימה.
    הקריאה היא אסינכרונית בפועל: אין צורך להמתין לחיוב שהתבצע – אלא רק ל Queue שהוא אכן קיבל את ההודעה. אם מערכת החיוב פונה לחברות האשראי ייתכן שייקח לה מספר שניות לבצע את החיוב, בעוד Queue יקבל את ההודעה ב מילישניות בודדות.
  3. מערכת החיוב בודקת את ה Queue כל הזמן אם יש הודעת. כאשר היא שולפת הודעות – היא מטפלת בהן ב\”זמנה החופשי\”.
המודל של Event Notification הוא פשוט ושימושי.
  • הוא מתאים כאשר מישהו רוצה לשלוח הודעה והוא לא מצפה לתשובה.
  • הוא מתאים כאשר הצד מרוחק יבצע את הפעולה בקצב שונה. למשל: בשל תקלה בחברת כרטיסי האשראי ייתכן שהחיוב יתבצע רק לאחר שעה (דוגמה קיצונית).
  • הוא מאפשר למערכת ניהול הנסיעות להיות בלתי תלויה במערכת החיוב: אם יום אחד רכיב אחר יטפל בחיוב / הטיפול יחולק בין כמה רכיבים – מערכת ניהול הנסיעות לא תשתנה כתוצאה מכך.
    • חוסר התלות הזו היא לא מושלמת: מה קורה כאשר מערכת החיוב זקוקה לנתון נוסף לצורך החיוב? (על כך בהמשך)
    • כלל טוב לצמצום התלות הוא לשגר אירוע \”כללי\” שמתאר את מה שקרה במערכת \”נסיעה הסתיימה\” ולא פקודה כמו \”חייב נסיעה!\”. שימוש במינוחים של פקודה גורם לנו לקבל בצורה עמוקה יותר את התלות בין המודולים – ולהעצים אותה לאורך הזמן.
  • כאשר יש ריבוי של Events Notifications במערכת – קשה יותר לעקוב אחרי ה flow, במיוחד כאשר events מסוימים מתרחשים רק לפעמים ו/או במקביל.
    Mitigation אפשרי הוא מערכת לוגים מרכזית ופעפוע \”request id\” (ואולי גם hop counter) על גבי ה events. כל כתיבה ללוג תציין את ה request id – וכך יהיה אפשר לפלטר את כל מה שהתרחש במערכת במערכת הלוגים ולראות תמונה שלמה. בערך.
עד כאן טוב ויפה. 
מה קורה כאשר מערכת החיוב דורשת עוד נתון ממערכת הנסיעות? למשל: האם הנסיעה התחילה בשדה תעופה או לא?
בגישת קיצון אחת, להלן הגישה העצלה – ניתן לשלוח ב event רק את id של הנסיעה שהסתיימה. מערכת החיוב תשלים את הנתונים החסרים ממערכת הנסיעות / מערכות אחרות.
בגישת קיצון שנייה, להלן הגישה הנלהבת (eager) – אנחנו מעדכנים את ה event לכלול את כל הנתונים שמערכת החיוב זקוקה להם.
בשני המקרים, יש לנו תלות מסוימת במערכת החיוב: שינוי במערכת החיוב עלול לדרוש שינוי במערכת ניהול הנסיעות – בגרסה אחת להוסיף שדה ב API של מערכת ניהול הנסיעות, בגרסה שניה – נתון על ה event.
איזו גישה עדיפה? – אין לי תשובה חד משמעית.
בד\”כ אני מעדיף את הגישה הנלהבת, כי:
  • יותר קל לעקוב מה מתרחש – כי אפשר להסתכל על ה event ולהבין אלו נתונים נשלחו – ובמקום אחד.
  • הערכים שעברו על ה event הם קונסיסטנטים ל event – לא יקרה מצב שבחצי שנייה (או דקה) שלוקח למערכת החיוב לבצע קריאה – אחד הערכים השתנה.
  • יש פחות קריאות ברשת, ומעט פחות דברים שעשויים להשתבש.
כמובן שאם יש נתונים שצריכים להיות fresh, כדאי לערבב בין הגישות – ולקרוא אותם ברגע האמת בעזרת API.
Event-Carried State Transfer
גישה זו היא וריאציה של גישת ה Event Notification, אבל שינוי אחד בה – משנה בצורה משמעותית את כללי המשחק:
  1. אפליקציית הנהג מודיעה שהנסיעה הסתיימה.
  2. מערכת ניהול הנסיעות שולחת את כל הנתונים שיש לה על ה event.
    איך שולחים את כל הנתונים? בד\”כ לוקחים את אובייקט המודל של ה ORM – ועושים לו serialization. 
  3. מערכת החיוב בודקת כל הזמן אחר הודעות. כאשר יש הודעה – היא קוראת ממנה רק את הנתונים שהיא זקוקה להם. היא עשויה לשמור עותק מקומי שלהם.
בעצם במקום להעביר הודעה, אנחנו מעבירים את ה state השלם של האובייקט בין המערכות השונות.

לגישה זו כמה יתרונות:

  • השגנו isolation גדול יותר (במימד אחד): שינוי במערכת החיוב לא ידרוש שינוי במערכת ניהול הנסיעות.
  • Availability – אם מערכת ניהול הנסיעות קרסה, ניתן להמשיך לבצע חיובים, כי למערכת החיוב יש את כל הנתונים שהיא צריכה.
לגישה יש גם כמה חסרונות:
  • שברנו את ה encapsulation: מערכת החיוב מכירה את מבנה הנתונים הפנימי של מערכת ניהול הנסיעות. מעכשיו יהיה קשה הרבה יותר לבצע שינויים במבנה הנתונים, ויש גם סכנה שהמתכנת של מערכת החיוב לא יבין את השדות נכון – ויפעל ע\”פ נתונים מוטעים.
  • העברנו הרבה נתונים מיותרים ברשת – בד\”כ זו בעיה משנית.
  • יצרנו עותקים שונים של הנתונים ברשת, מה שפוטנציאלית יוצר בעיה של Consistency בין הנתונים. נתונים שכן צריכים להיות up-to-date לצורך הפעולה – יהיו לא מעודכנים ויתכן שיהיה צורך בליישם מנגנון של eventual consistency.
שבירת ה encapsulation היא מבחינתי השבר העיקרי.
מרטין פאוולר ביטא זאת יפה, בנחמדות בריטית אופיינית: \”זו גישה שטוב שתהיה בתחתית ארגז הכלים שלכם\”. אפשר להשתמש בה – מדי פעם.

מה קורה כאשר מידע נוסף נמצא על מערכת שלישית? למשל, את הפרט אם נסיעה התחילה בשדה תעופה (ואז יש לתת 30% הנחה ;-)) ניתן להסיק רק כאשר יש נתונים נוספים ממערכת האזורים?

גם כאן יש בחירה: אפשר לתת את המשימה למערכת ששולחת את ה event, או לזו שמקבלת אותו. כנראה הבחירה תעשה ע\”פ איזו תלות בין המערכות – היא סבירה יותר.

Event Sourcing

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

אם מישהו רוצה לקרוא את האובייקט – הוא צריך להרכיב את שרשרת השינויים בכדי לקבל את האובייקט העדכני.

מה התועלת בגישה הזו?

  • אם אנחנו מקבלים עדכוני state מכמה מקורות – אין לנו race condition בו מקור א\’ מוחק את השינוי של מקור ב\’.
    זה יכול להתרחש אם מקור א\’ קרא עותק ישן של האובייקט, לפני השינוי שמקור ב\’ ביצוע – אבל ההודעה ממנו הגיעה אחריו.
  • אנחנו שומרים היסטוריה של האובייקט ושינויי המצב שלו. אם נרצה – נוכל להרכיב את מצב האובייקט בכל רגע נתון (בהנחה ששמרנו את הזמן שבו קיבלנו את ההודעה).
    • זה יכול להיות שימושי לצורך debugging / הסבר התנהגות המערכת.
  • ההודעות שנשלחות הן קטנות (רלוונטי כאשר האובייקט השלם הוא גדול)
יש גם כמה חסרונות:
  • הרכבה של האובייקט, במיוחד אם קיבל רשימה ארוכה של עדכונים – היא פעולה יקרה יחסית.
    • החיסרון הזה הוא בעייתי במיוחד אם הרכבה של האובייקט דורשת נתונים נוספים ממערכות אחרות.
    • החיסרון הזה מתמתן אם אנחנו מחזיקים עותק של הנתונים בזיכרון.
  • מה קורה כאשר הסכמה משתנה? כלומר: מבנה הנתונים?

פה עשויה לעלות שאלה פילוסופית: אם אני מקבל את העדכונים כ delta, אבל אז בכל עדכון עושה merge עם האובייקט שאני מחזיק אצלי – האם זה עדיין Event Sourcing?

אפשר לומר שכן – ההצהרה הזו עדיין תעזור לאנשים לקבל במשפט אחד תובנה על המערכת. מניעת racing condition הוא ערך גדול בפני עצמו. יש פה tradeoff כמובן: ביטול חסרונות משמעותיים – מול איבוד כמה מהיתרונות האחרים.  זהו tradeoff סביר לחלוטין.

Command Query Responsibility Segregation (בקיצור: CQRS)

מספרים שאם הייתם מחפשים בגוגל \”CQRS\” לפני עשור, הוא היה שואל: \”`?did you mean `Cars\”
הרעיון הוא דיי ישן, ומקורו בשנות השמונים, אבל רק בשנים האחרונות הוא הפך למאוד-מוכר.

אני מניח שהרוב הגדול של הקוראים מכיר את השם, אבל לא בהכרח מכיר את הרעיון מאחוריו. לרוב האנשים CQRS מתקשר ל \”high performance\”.

האמת שהרעיון של CQRS אינו קשור קשר ישיר ל events, אבל פעמים רבות – משתמשים בו כך.

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

מתי זה שימושי?

כאשר דפוס הקריאה ודפוס הכתיבה שונים זה מזה.

למשל: נניח בטוויטר (אני מספר מהזיכרון – ייתכן שזה לא מה שקורה שם) כתיבה של טוויט (להלן: Command) הולכת למודל הכתיבה. שחררתי את הטוויט מהר והמשכתי לאינסטגרם.

כאשר משתמש אחר נכנס לטוויטר, הוא רוצה לראות את הפיד של הטוויטים מיד. אם נתחיל לעשות Query אחר כל האנשים שהוא עוקב אחריהם, וכל הטוויטים שלהם, ואז נמיין אותם ע\”פ הסדר -זה ייקח הרבה זמן! יותר מדי.

במקום זה, לאחר שכתבתי את ה tweet יש Background Processor שמעתיק את הטוויט שלי לפיד של כל העוקבים.
כלומר:

  • מודל \”הכתיבה\” הוא רשימה של טוויטים ע\”פ מחבר.
  • מודל \”הקריאה\” הוא הפיד של כל משתמש בנפרד.
זה אומר שיש הרבה שכפול נתונים במערכת, ושטח האחסון הנדרש הוא אדיר. אם יש למישהו מיליון עוקבים – כל טוויט ישוכפל מיליון פעמים.
מצד שני, זה גם אומר שגם אם אני עוקב אחרי 1000 פרופילים ויותר – הפיד שלי ייטען ב (O(1.
במקרה של טוויטר סביר שמודל הכתיבה ומודל הקריאה הן בכלל מערכות שונות – כאשר כל הוספה של טוויט למודל הכתיבה – שולחת אירוע של עדכון (event notification) למודל הקריאה – שם נמצא ה Background processor.
מכיוון שלא ממש משנה אם אני מקבל את הטוויטים מיד או אחרי דקה או שתיים מרגע שצויצו, ומכיוון שלא כ\”כ משנה עם הסדר של הטוויטים אצלי הוא אותו סדר כמו אצל חבר שלי העוקב אחרי בדיוק אותם פרופילים – המודל הזה עובד.

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

שימוש אחר של CQRS הוא לא דווקא מבחינת ביצועים גבוהים, אלא פשטות של הקוד. אם המודלים סבוכים למדי – החלוקה ל\”מודל כתיבה\” ו\”מודל קריאה\” יקטינו את ה code base בחצי, בערך.

כאן שווה לציין ש Event Sourcing ו CQRS הולכים יד ביד זה עם זה:
מודל הכתיבה הוא ה State Log – אבל יש מודל קריאה שהוא המצב העדכני. זה יכול להיות בסיס נתונים או טבלה אחרת בה שומרים את המצב העדכני, וזה יכול להיות מודל שעובד מעל אותם נתונים – ורק מכיל את הקוד של \”השטחת\” העדכונים בזמן ה Query.

סיכום

התלהבתי מהסדר שפאוולר עשה בנושא ה Event-Driven, ולכן כתבתי את הפוסט והוספתי עוד כמה תובנות משלי.
השארתי קצת אפור בהגדרות של הגישות השונות. תמיד ניתן לערבב ולייצר וריאציות. למשל:

הייתי מעורב בבניית מערכת שמבצעים בה רפליקציה של נתונים לשירותים אחרים, כמו בגישת ה Event-Carried State Transfer – בכדי להשיג High Availability. מצד שני, כמות הנתונים שמועתקת היא קטנה ומדודה מאוד, והנתונים הם ברמת הפשטה של ממשק ולא מבנה נתונים פנימי – כך שאין פגיעה בהכמסה של המערכת.

אם הייתי מנסה לתעד כל וריאציה שימושית בפני עצמה – כנראה שהיינו גומרים עם 16 צורות לשימוש ב Events ולא ארבעה, מה שהיה מאריך את הפוסט אבל יותר גרוע: מקשה על יצירת \”שפה משותפת\” שאנשים זוכרים וחולקים.

אז מה הופך מערכת להיות Event-Driven? – לא תצאו עם תשובה חד משמעית מהפוסט.
יצא לי לעבוד על מערכת בה השתמשנו בכל ארבעת הגישות, ולרגע לא חשבתי לקרוא למערכת \”Event Driven\”…. מוזר.

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

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

ההרצאה של פאוולר ב Goto; Chicago
פוסט של פאוולר בנושא

ארכיטקטורות ללא שרת (Serverless Architectures) – מה זה השטויות האלה?!

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

“עכשיו תעשה לי את זה בלי שרת” – מבקש המראיין.
ווב, בלי שרת? כלומר… Rich Client שלא מתקשר עם אף אחד?

“לא. בדיוק רק מה שהצגת – אבל בוא נבטל את השרת”.
לרובנו השלב הבא יהיה להבין לעזאזל מה חושב המראיין (??). זה איזה תרגיל לוגי מתחכם? אולי תרגיל בבחינת האישיות שלנו? אולי בעצם הגענו לראיון במחלבה של תנובה, ולא בחברת הייטק?!

מאז שנות ה-80, מודל ה Client-Server הוא המודל העיקרי של מערכות תוכנה, והוא עובד טוב. יש טרנדים: פעם לקוח רזה, ופעם לקוח שמן. פעם שרת מרכזי, ופעם שרת-רזה. אבל בכל זאת, ובמיוחד מאז עליית האינטרנט בשנות ה-2000 – אין כמעט מערכות שאנו משתמשים בהן שלא מחוברות לאיזשהו שרת (חוץ מכמה אפליקציות אופיס, Photoshop, או משחקים – וגם זה משתנה).

אז איך בדיוק אנחנו נבנה מערכות ללא-שרת? האם זה רק גימיק שיווקי (למשל: “השרת הוא בענן”), פתרון ספציפי לצרכים מיוחדים, או אולי באמת בסוג של מהפכה?

הרי קשה להתעלם מהבאזז המוזר הזה של “Serverless Architectures”, באזז שכולל Frameworks, ספרים, ואפילו Conference שמוקדש לנושא.

בפוסט הזה אנסה להסביר את הנושא. נראה שבעצם כל התשובות נכונות.

הכרזה של ServerlessConf בניו-יורק

אז מה בעצם הכוונה ב “Serverless”?

כמו באזזים שונים שנתקלתי בהם בעולם התוכנה לאורך השנים (“SOA”, “MVC”, או “Big Data”), חוסר בהירות או אחידות בהבנת העקרונות הבסיסיים מאחורי הבאזז – לא מונעים מהבאזז לפרוח (אולי אפילו להיפך). זה קצת כמו הברקזיט: קודם מצביעים – ואז הולכים להבין במה מדובר 😉

את באזז ה Serverless ניתן לקשר לשלושה כיוונים עיקריים:

BaaS (קיצור של Backend as a Service) – שירות המאפשר למפתחי צד-לקוח (בעיקר מובייל, ולכן לעתים נקרא גם MBaaS) לבצע bootstrapping[א] מהיר ללא הצורך בידע והשקעה בצד השרת.
שירותים כמו parse.com (שנקנתה ע”י פייסבוק ואח”כ נסגרה), Firebase, או Kinvey הפכו פופולריים בעולם הסטארטאפים, וקיימים גם פתרונות פופלארים בקהילות הסגורות של עולם ה Enterprise (יבמ, אוקרל, סאפ) שבוודאי יהיו פחות מוכרים לאיש התוכנה הממוצע.

שירותים אלו מספקים סט יכולות סטנדרטי (כ API), שבעצם פותר את עיקר הצרכים של אפליקציות מובייל בתחילת דרכן: שמירת נתונים, למשמש או מידע שישותף בין המשתמשים. ניהול הרשאות, אנליטיקס ו notifications למשתמשים. לכל פלטפורמה יש כמה יכולות נוספות משלה.

הסטארטאפ יכול בעצם להתמקד באפליקציית המובייל, ובעלות זניחה יחסית – לקבל שירותים בסיסיים בצד-השרת השמאפשרים “להרים” אפליקציה במהירות. בעתיד, ובמידה שהאפליקציה תצליח – יהיה ניתן להעביר את פונקציונליות השרת בהדרגה לפתרון custom made שיתאים בצורה מדוייקת יותר לצרכים.

האם ב BaaS אין שרת? – יש שרת, הוא פשוט מוצר מדף “סטנדרטי”.
האם זו נישה? – במידה מסוימת כן. סטאראטאפים בתחילת דרכים.
האם זו גישה חדשנית או אפילו מהפכנית? – כן, אם אתם סטאראטאפ שנופל לקטגוריה.

FaaS (קיצור של Functions as a Service) היא הגל השני של ה Serverless Architectures, שעלה לכותרות בעיקר בעקבות ההצגה של שירות AWS Lambda. למרות שהשירות שוחרר בגרסתו הראשונית עם מגבלות רבות, הוא הגיע משחקן מוכר ומוערך מאוד (אמזון), עם מחיר כניסה אפסי (אפשר להתנסות בו במחיר של סנטים), ובמרחק נגיעה – כי למאות אלפי (?) מתכנתים יש כרטיס אשראי כבר מוזן באמזון, והם יכולים להפעיל את השירות במרחק של קליק.

הפתרון, בגדול, מאפשר לכתוב ולעשות deploy לפונקציה בודדות – שתופעל כתגובה לקריאה ל endpoint (נקראים: “event sources”) שנגדיר.
תפעול הפונקציות הללו (ניהול עומס, monitoring, ו High Availability) מנוהל ע”י אמזון. רק מעדכנים את קוד הפונקציה – ואמזון דואגת לשאר.
בעצם FaaS הוא סוג של PaaS (כלומר: Platform as a Service, סליחה על השימוש התכוף בבאזזים) ברזולוציה קטנה הרבה יותר: במקום אפליקציה – פונקציה.

מאז הצגת AWS Lambda הזדרזו המתחרים להציג שירותים מקבילים, והיום יש לנו גם את Google Cloud Functions (עדיין באלפא, בעת כתיבת פוסט זה), את Azure Functions (גם הוא חדש), ואת OpenWhisk של יבמ (שרצה על פלטפורמת Bluemix של יבמ, פלטפורמה מוכרת בכנסים – וקצת פחות מפתרונות בפרודקשיין).

במקביל לענקיות הענן, ישנם גם מפתרונות של שחקנים קטנים, למשל:StackHut או WebTask.

האם ב FaaS אין שרת? – יש קוד צד-שרת, אבל בעצם מדובר בסט של פונקציות עצמאיות המנוהלות ע”י מישהו אחר. יש צד-שרת, למרות שאין “שרת”.
האם זו נישה? – כרגע כן. הרבה משחקים באופציה החדשה, מתלהבים (“יו! פאקינג אינסוף Scalability!!”), אבל גם מתפכחים (“אהה.. אבל ה DB הוא צוואר הבקבוק של ה scale” / “קצת נהיה בלאגן” / “זה יוצא דווקא דיי יקר…”).
האם זו גישה חדשנית או אפילו מהפכנית? – אולי. נהיה חכמים יותר עוד שנתיים – שלוש. עדיין יש פה גישה חדשה שמאתגרת הרבה מאוד ממה שהתרגלנו אליו עד עכשיו בעולם צד-השרת.

תת-וריאציה (מעט משונה) של FaaS היא DBFaaS, הגישה הזו גורסת שלעתים קרובות אנו זקוקים ב FaaS לפנוקציות שמבצעות עיבוד קל על נתונים. היכן יותר יעיל לשים את הפונקציות הללו – אם לא ב Database עצמו?
לחברת SAP יש מוצר בשם HANA, בסיס נתונים in-memory, שמאפשר ממשק וובי ישיר ל stored procedures שלו.
גישה זו שוברת כמעט כל מוסכמה של Layered Architecture או MVC, ומציבה דאגות רבות (Scalability? אבטחה? יכולת debugging ותהליכי תוכנה נכונים?). אני עדיין לא מצאתי איזון בריא לגישה הזו – אך אין ספק שהיא מערערת מוסכמות וגורמת לחשיבה מחודשת של הדברים. למה בעצם לא??

טרנפורמציה של ארכיטקטורת Client-Server לארכיטקטורת Serverless. מקור: Bliki

Serverless Web Site (אין קיצור מגניב)

תצורה אחרונה, וקצת פחות מהותית מהאחרות אליה מתייחסים כ Serverless Architecture היא לארח אתר אינטרנט (לרוב עם פונקציונליות מוגבלת, ובעיקר חוסר-תקשורת בין המשתמשים השונים) כ Static Content, ובניית כל הפונקציונליות ב JavaScript.
את קובצי ה HTML/CSS/JavaScript מארחים בשירות אכסון כמו S3 או אפילו עדיף – CDN.

הם בגישה זו אין שרת? – אפשר לומר שלא. ניתן להתייחס ל CDN כ”תשתית רשת”.
האם זו נישה? – כן.
האם זו גישה חדשנית או אפילו מהפכנית? – לא ממש, אם כי היא אפשרית בעקבות ההתפתחות של שפת ה JavaScript ויכולות שונות בדפדפן מהשנים האחרונות. יש אנשים שיישום השיטה הזו גורם להם לסיפוק רב.

כמה שהגישות השונות שהצגתי הן שונות זו מזו – יש ביניהן סינרגיה.

כאשר אנו משתמשים ב BaaS, תחת היכולות הגנריות שמציע השירות הספציפי – מה יותר טבעי מלהוסיף קצת custom server functionality כ FaaS?

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

בכל מקרה, החידוש העיקרי והעכשווי הוא סביב FaaS – ובו נתמקד בשארית הפוסט.

מקור: אמזון. לטעמי השימוש כאן במונח “Microservice” הוא לא ממש מדויק.
אם היו גם מציינים גם Big Data, דוקר, ו IoT – זה היה כבר יותר הגיוני 🙂

אז מה הם באמת התכונות העיקריות של ארכיטקטורה “ללא-שרת” (קרי: מבוססת FaaS)?

אפשר לייחס ל Serverless Applications את התכונות הבאות:

  • התבססות במידת האפשר על שירותי צד-שלישי.
  • ה Flows העיקריים של האפליקציה מנוהלים בצד-הלקוח. צד השרת מספק בעיקר “פונקציות”.
  • בניגוד לשרת שחי לאורך זמן, וטיפל בבקשות שונות – ב Serverless Architectures המופע של צד-השרת חי לאורך טיפול בבקשה. יכולים להיות אלפים כאלו שמופעלים ונדומים בשנייה.
    • זו תכונה טכנית יחסית, שעשויה להשתנות. ייתכן והספקים יתחילו לספק הנחות למי שמבטיח כמות מסוימת של שימוש בשעה – והדרך להוזיל עלויות תהיה כן להחזיק כמות מסוימת של instances קבועים.
    • יתרונות נוספים של instances קבועים הם cache “חם” (ברמות השונות) וביטול / קיצור ה initialization latency.
  • ארכיטקטורות Serverless לוקחות את רעיון ה Continuous Deployment לאקסטרים חדש: כעת ניתן, בכל רגע, לבצע דיפלוי ברזולוציה של פונקציה בודדת.
יתרונות:
  • חסכון בעלויות, כי משלמים רק על מה שרץ – במיוחד כאשר יש traffic דליל. בסקייל בינוני ומעלה – זה יותר יקר.
  • יותר אופרציה מנוהלת ע”י ספק השירותים, או קצת בהקצנה: noOps#. רעיון ה Platform as a Service (בו כמעט כל היבטי ניהול אפליקציות מבוצע ע”י הספק) לא הצליח כ”כ בפועל, אך יש סיכוי שמודל ה FaaS יצליח יותר.
  • כאשר כל פונקציה (עם מאפייני הביצועים הייחודיים שלה) היא מבודדת – קל יותר לעשות Scaling. טעות נפוצה היא ש FaaS הוא “infinitely scalable”. כאשר יש לפונקציה state משותף כזה או אחר – צווארי הבקבוק של ה scalability יהיו שם – כפי שהיה תמיד.
  • אפשרות לקרב את הפונקציה למשאב אחר, למשל: קרוב מאוד לשירות צד-שלישי ולבצע חישובים שם, קרוב לנתונים, או אולי קרוב ללקוחות (למשל: לשים פונקציות שירוצות אצל ספק ה CDN וכך יספקו תשובות מאוד מהירות למשתמשי הקצה שלי, בכל רחבי העולם).
חסרונות:
  • חלוקה של מערכת להרבה פונקציות קטנות דיי מהר הופכת לאתגר תפעולי מצד המתכנתים. רבים מהמימושים המוצלחים של FaaS כרגע – מבוססים על פונקציות מעטות.
  • חלוקת המערכת להרבה פונקציות קטנות עלולה ליצור קשיים בהשגת אמינות גבוהה: הרשת יכולה לשבש קריאות בין פונקציות שונות – ואם אנו זקוקים ל”אפס פספוסים”, אנו נצטרך להתגונן בפני כשל של הרבה מאוד נקודות אינטגרציה.
  • Lock-In ל Vendor המספק לכם את השירותים. אולי הפונקציות עצמן מבודדות (isolated), אך סביר שהן משתמשות ב infrastructure נוסף (הרשאות, API Gateway, אכסון נתונים, וכו’) שכובל אתכם לספק הספציפי.
  • כאשר כל פונקציה רצה בפני עצמה בשרת צד-שלישי, ולא ניתן להריץ את הקוד לוקאלית – הפיתוח נעשה מורכב יותר.
    • לא יפתיע אותי אם נראה בקרוב יותר ויותר אמולטורים שמאפשרים להריץ את פתרונות ה FaaS (בצורה פחות יעילה / אמינה – רק לצורך פיתוח) על המחשב המקומי.
  • לפחות כרגע, לפתרונות כמו AWS Lambda יש Initialization latency לפונקציה – כלומר: אתחול הפונקציה מוסיף לזמני התגובה כ 100-600 מילישניות (ע”פ דיווחים שונים). זה בסדר ל Event Processing, אבל קצת פחות טוב ל UI או מערכות semi-realtime.

איזה סוג של מערכות אם כן, מתאימות יותר ל Serverless Architectures?

  • UI-Centric Apps – אפליקציות בהן חווית המשתמש היא המרכזית, והצרכים מצד השרת הם מצומצמים. אלו יהיו בעיקר אפליקציות מובייל – אך לעתים גם מערכות ווב.
  • Message-Driven Systems – מערכות שעיקר עיסוקן הוא טיפול באירועים, למשל: טיפול בטרנזקציות בנקאיות, איתור Fraud, או מערכת שמחליטה איזו מודעה להתאים למשתמש. מערכות אלו ניתן לפרק בקלות יחסית לסדרה של פונקציות, כאשר יש הגיון לשפר כל פונקציה בנפרד: הן מבחינת ביצועי תוכנה = לרוץ מהר יותר, והן מבחינת ביצועים עסקיים = לתת תשובה קצת יותר מדויקת.
    • אם המבנה הלוגיקה העסקית הוא של Pipes and Filters – מבנה ועקרונות של Serverless Architectures עשויים בהחלט להיות רלוונטיים.
    • באזז נוסף שמתקשר ל Message-Driver Systems ו FaaS הוא IoT (קיצור של Internet of Things): אירועים שמגיעים מהמון מכשירים קטנים.
  • חיזוק לנאמר לעיל: מערכות בהן אין (או כמעט ואין) State בצד השרת.
    • בשפה של תכנות פונקציונלי: הפונקציות של FaaS הן Pure Functions.
  • (קצת תיאורטי) יש טיעון שמערכות שחוות spikes גדולים מתאימות ל Serverless Architecture בגלל הציפיה לתשלום ע”פ גרנולריות מדויקת של שימוש, ויכולת Scalability גבוהה כאשר הפונקציות הן stateless.
    • כאשר AMI של אמזון (שנבנה בצורה המתאימה) יכול לעלות ולהיכנס לשימוש בטווח של דקה או שתיים – רוב ה spikes יכולים להיות מטופלים בצורה סבירה עם autoscaling. קשה לי להאמין שהעלויות של FaaS יוכלו להתחרות בעלויות של ניהול התשתית בעצמנו (IaaS) – כאשר מדובר ב Scale גבוה. אין ארוחות חינם.

לגבי העלויות ארצה לציין זאת במפורש: יש אינסוף אזכורים לכמה AWS Lambda עשויה זולה יותר מ EC2. שמעתי לא פעם את המספר “80% חסכון!”. זה סיפור טוב. כשצוללים לפרטים, ניתן לראות סיפורים על חסכון משמעותי – כאשר יש 3 קריאות ביום (מול שרת t2.micro).

יותר קשה למצוא ניתוחים של עלויות AWS Lambda ב scale גבוה. כל הניתוחים הללו שראיתי (הנה דוגמה) מראים מחיר גבוה יותר בשימוש ב Lambda מאשר בשימוש ב EC2.

סיכום

“כמה זמן יעבור עד ש Serverless Architectures יהיו הסטנדרט?” – היא שאלה שכבר שמעתי.
“כמו שהענן הולך להעלים את תצורות ה On-Premises… הרי Serverless יעלימו את ה Client-Server”

האמת – שאני לא יודע.
ייתכן וזה באזז שיחלוף, וייתכן שלגישת ה Serverless Architectures תהיה השפעה רבה על עיצוב מערכות מכאן ואילך.

אנשים רבים מבלבלים או מחליפים בין Microservices ל FaaS: מתארים פונקציה בודדת פשוטה (FaaS) כמיקרו-שירות.
למשל: שמעתי מישהו שהסביר שמיקרו שירות הוא Fully Stateless בהגדרה, ואסור שיהיו לו תלויות בשירותים אחרים.
הוא תיאר ככל הנראה פונקציה ב FaaS – ולא מיקרו-שירות.

למרות שיש דמיון בין הגישות, קרי: חלוקת המערכת לחלקים קטנים הרבה יותר, יש הבדל מהותי במוטיבציות:

במיקרו שירותים מחלקים מערכת גדולה ומורכבת על מנת שהמתכנתים (שמספרם הולך וגדל בשלב hyper-scaling של החברה) יוכלו להשתלט על הקוד ביתר קלות, ועל מנת להשיג Continuous Deployment.
אם המערכת לא כ”כ מורכבת – ההמלצה היא להישאר עם מונוליט. כמו כן, ההנחה היא שחלק גדול מהשירותים הולכים לשמור מידע בבסיסי נתונים כאלה ואחרים – ויש הרבה קשרים בין השירותים.

ב FaaS לוקחים חלקים מאוד ספציפיים מהמערכת (או מהמיקרו-שירות), בד”כ חלקים פשוטים, ולהוציא אותם החוצה. המוטיבציה היא מכלול של שיקולים שונים כמו: ניהול ע”י צד שלישי, Scalability גבוה, קרבה למשאבי מחשוב (למשל: לשים פונקציות מסויימות על ה CDN שלי כך שיהיה קרוב למשתמשים ויספק תשובה במילי-שניות ספורות), וכו.
חלוקה שכזו עובדת טוב על פונקציות שיש להן מינימום תלויות, וכמה שפחות state – או לפחות: shared state.

חשוב להבין את המוטיבציה, וה tradeoffs הנתונים לכל גישה – ולא להיסחף אחרי “סיפורי הצלחה” של ארגונים אחרים, עם בעיות אחרות – שאולי לא שקולות לבעיות שעליכם לפתור.

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

[א] קרי – להעמיד מוצר ראשוני / התחלתי

הכנס השני לארכיטקטורת תוכנה (30 לנובמבר – 1 בדצמבר)

בסוף החודש הקרוב, 30 בנובמבר – 1 בדצמבר, יתקיים בהרצליה הכנס השני לארכיטקטורת תוכנה.

הכנס מאורגן ע\”י IASA ואילתם.

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

ILTAM, היא קהילה מקצועית, רחבה יותר, המורכבת בעיקר מחברות הייטק גדולות ומבוססות (לא רק חברות תוכנה נטו: אלתא, 3M, וצה\”ל למשל – הם חברים) במטרה לקדם ולשתף ידע.

בשונה משנה שעברה בה הייתה נוכחות גדולה של האקדמיה וחברות מהגדולות במשק – עיקר המשקל השנה ניתן לחברות סטארט-אפ ונושאים שרלוונטיים (גם) עבורן.

היום ראשון מורכב מהרצאות. הנה התכנית:

ביום שני מתקיים Tutorial בהדרכתה של Rebecca Wirfs-Brock (שהגיעה לארץ במיוחד, אני מניח), בנושאי ארכיטקטורה באג\’ייל ו Quality Attributes בפרט (הנה פוסט שפירסמתי בנושא, אם אתם רוצים לקבל מושג במה מדובר).

האם כדאי לבוא?

תקשיבו, זו שאלה דיי אינדיבדואלית, ואני בד\”כ זהיר במתן המלצות. בכל זאת, כשאני מסתכל התכנים – נראה לי שהצליחו לרכז באמת שורה של נושאים ומרצים מעניינים ביום הראשון – שרלוונטיים לאנשי-תוכנה כמעט מכל הסוגים.
היום השני הוא באמת ממוקד יותר לארכיטקטים, או מי שרוצה שהתעמק בטכניקה תאורטית שהתמורה שלה להשקעה היא ארוכת-טווח. אני לא יודע להמליץ ספיצית על ה Tutorial שנבחר, אבל אם הוא נבחר באותה רוח של בניית האג\’נדה ליום הראשון – ייתכן בהחלט וזה יהיה Tutorial מוצלח!
  • אני נותן הרצאה על מיקרו שירותים (עדיין לא החלטתי בדיוק איך להעביר את הנושא…). אם אתם מגיעים – קפצו לומר שלום!
  • קצת אחרי ייתן הרצאה יונתן ממן, שכתב כאן פוסט אורח בנושא – ממש לאחרונה.
  • הנה אתר הכנס: http://conference70.wix.com/sw-architecture
  • בטופס ההרשמה שבאתר, ניתן לקבל הנחה אם מזינים את המילה \”Presenter\”, בסעיף של קבוצת שיוך (אופס, אני מקווה שבאמת היה מותר לי לספר את זה…).
שיהיה בהצלחה!
ליאור
 

AWS: “השירותים הפשוטים” של אמזון – חלק ב’, וארכיטקטורה מונחית-אירועים

בפוסט הקודם כיסינו שני “שירותים אפליקטיביים” בסיסיים של AWS: שירות ההודעות SNS, ושירות התורים SQS.
בפוסט הזה נמשיך את הסקירה ונכסה את שירות ה Workflows שנקרא SWF – שירות שימושי, אך קצת פחות מוכר.

Simple WorkFlow Service (בקיצור SWF)

SWF בא לפתור לנו כמה בעיות שלא נפתרות ב SQS או SNS. למשל:

  • נניח שיש לי סדרה של הודעות בין שירותים הקריטיות לביזנס, שעלינו לוודא שכולן טופלו בהצלחה + לדעת מתי כולן הסתיימו.
    כיצד מתמודדים עם משהו שכזה בעזרת SQS? מחזיקים הודעות אימות ואז סורקים אותן כל כמה זמן?! – לא יעיל.
  • נניח שיש לי מקביליות-חלקית ברצף של הודעות שבהן ארצה לטפל: חלק מההודעות עלי לשלוח בזו אחר זו, אבל חלק ניתן לשלוח במקביל – ולקצר את התהליך.
    כאשר אני שולח הודעות ב SNS או SQS  אין לי שליטה מה קורה איתן, ובטח שאינני יכול לתזמן את הטיפול בין הודעות שונות….
הפתרון הפשוט לבעיה זו הוא לנהל רצפי-הודעות שכאלה בצורה ריכוזית של תקשורת “הודעה-תשובה” בקוד של שירות כלשהו. למשל שירות ‘A’:

  • שירות A שולח את הודעה 1 לטיפול ומחכה שתסתיים.
  • שירות A שולח את הודעות 2, 3, ו 4 לטיפול במקביל (משיקולי ביצועים). הוא מממש Pattern של Monitor – שנותן אות ברגע שהטיפול בשלושת ההודעות הסתיים.
  • שירות A שולח את הודעה 4 לטיפול – והנה כאן ה”טיפול המיוחד” מסתיים.

הקוד שעלי לכתוב הוא לא מסובך, אבל גם לא סופר-פשוט (תלוי מאוד בשפת התכנות וספריות-העזר שיש בידי).
קשה יותר לכתוב אותו שיהיה יעיל ו Scalable (שוב: תלוי בשפה / סביבת ריצה), וקשה אפילו יותר לכתוב אותו שיהיה גם Highly Available.

לצורך כך צמחו שירותים נוסח SWF או IronWorker, שמספקים תשתית אמינה, יעילה, ובדוקה היטב לטפל בקלות ברצפים כאלו של הודעות, מה שנקרא גם “Workflows”.

רגע של תיאוריה

ישנו סגנון ארכיטקטוני שנקרא Event-Driven Architecture (ארכיטקטורה מונחית-אירועים, להלן EDA).

לכאורה, כל פתרון בו יש הודעות א-סינכרוניות – יכול להיחשב “סוג של EDA”: כל אפליקציית UI או קוד ג’אווהסקריפט
בפועל, החכמה ב EDA היא לא עצם השימוש בהודעות / תקשורת א-סינכרונית, אלא בארגון שלהן.

לכל סגנון אינטראקציה של הודעה יש יתרונות וחסרונות (שלא לומר Pitfalls). אפשר בקלות לפשט את הקוד בעזרת שליחה של הודעות, רק בכדי לגלות מאוחר יותר שהוספת יכולות מסוימות לקוד, או ניטור שלהן – הוא בגדר ה”לא-סביר”.

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

למשל, אפיון לדוגמה של אינטראקציה של הודעות יכול להיות:

  • Broker – מתווך ביניים שיוצר decoupling בין שולח ההודעה, ובין המקבל שלה, אך עושה זאת בתצורה של “הודעה-תשובה”.
  • Message Broker – שהוא כמו Broker, אבל עובד בתצורה של “שגר ושכח”
  • Publisher-Subscriber, תצורה של Message Broker עם Fan Out, כלומר: שליחת הודעה אחת וקבלה שלה ע”י כמה נמענים (נוסח SNS של אמזון).
  • Message Queue – נוסח SQS של אמזון.
  • ועוד ועוד…
מכיוון שיש הרבה סוגי אינטראקציה אפשריים, ועל כל אחד ניתן לעשות כמה וריאציות, ההמלצה היא קודם כל לחשוב ב “טופולוגיות” ורק אז לבחור את סוגי האינטרציה. קיימות 2 טופלוגיות מרכזיות:
  • Broker Topology – שליחה וטיפול בהודעות בודדות ובלתי-תלויות.
    כל הודעה עומדת בפני עצמה, והמערכת שלנו היא כמו “כוורת דבורים” של שליחת הודעות וטיפול בהודעות – ש”זורמות מעצמן”, ללא ניהול מרכזי.
  • Mediator Topology – ההודעות, או לפחות חלק מהן, אינן זורמות באופן עצמאי – אלא מנוהלות במסגרת מקומית מסוימת.
    למשל: יש לנו בכוורת כמה “דבורים סמליות (sergeant)” שמנהלות בצורה אקטיבית כמה תהליכים שהוגדרו כמורכבים או קריטיים במיוחד. ה Mediator הוא בעצם סוג של Workflow Engine. הנה דוגמה:
טופולוגיה של Broker. מקור – Mark Richards
בתרשים למעלה מתוארת טופולוגית Mediator. בתחתית התרשים אנו יכולים לראות שירותים שונים (Processors) שיודעים לטפל בהודעות. הם יכולים לעבוד בכמה תצורות שונות, למשל: בתצורה בה שולחים הודעה ומספקים כתובת (queue אחר, בד”כ) לשלוח אליו את ההודעות שטופלו (במידה וזקוקים לתשובה).
ה Mediator מנהל עשרות תורים קטנים (בשם Channels, למעלה), כאשר כל תור מתאר instance של Workflow בהרצה. ה Mediator מחזיק State Machine המאתר את ה Workflow. בכל שלב הוא שולח הודעות א-סינכרוניות (בד”כ) ל Processors הנכונים (בתרשים למטה לכל processor יש תור), וברגע שטיפול בהודעה הסתיים, הוא עובר שלב ב State machine, וכך יודע מה ההודעה הבאה שעליו לשלוח – עד סיום ה Workflow.
—את ה Mediator (= דפוס עיצוב) ניתן לממש לבד בקוד. שירות SWF הוא מעין “תשתית” שמאפשרת ליישם Mediator בצורה קלה ואמינה יותר.

הערה: SWF הוא לא חדשני. יש הרבה Frameworks לניהול Workflows (שמות נרדפים הם Process Integration, EAI, וכו’), ותיקים ומשוכללים בהרבה. כמו ששמו מעיד עליו: הוא שירות פשוט ובסיסי למדי, אבל שיכול לספק אמינות גבוהה ואינטגרציה טובה לסביבת אמזון.

ניתן לתאר את עיקר התכונות של SWF באופן הבא:

  • שירות מבוזר, אמין, highly scalable, המנוהל כשירות.
  • השירות מספק בעיקר כלי ניהול והרצה של ה workflow – קרי Mediator.
    את ה activities – יהיה עליכם לממש לבד (בג’אווה, רובי, וכו’) ולעשות deploy של הקוד על מכונות EC2 שבבעלותכם או אפילו מכונה מרוחקת (לא על AWS). מה ש SWF עושה הוא לקרוא לקוד שלכם ברגעים הנכונים, אבל הלוגיקה – היא בבעלותכם.
  • ניתן לשלב בצעדי ה Workflow קריאה לשירותים שלא רצות בענן (למשל: אפליקציות on-premises) או פעולות אנושיות (למשל: אישור או דחיה של בקשה).
  • ה workflow יכול לחיות עד כשנה (ניתן להגדיר retention period משלכם לכל workflow), לאחר מכן – אמזון תמחק אותו.
  • את ה workflow מנהלים בתוך domains, שלרוב נקצה אחד כזה לכל אפליקציה (לצורך ארגון והפרדה).
    • כל domain יכול להכיל מספר workflows.
    • workflow מדומיין A מנוע מלתקשר עם workflow מדומיין B.
  • ה state של ה Workflow execution, נשמר במקום אמין במיוחד (S3?) שמבטיח שלא סביר [א] שהוא יאבד.

השחקנים העקריים ב Workflow של SWF הם:

  • Activity Worker – הוא מי שמבצע את ה Activity. לפעמים זה יהיה חישוב פשוט, ולעתים – delegation של העבודה לחלק אחר של תוכנה, או לאדם שייקח החלטה.
  • Decider – לוקח החלטה מה לעשות ברגע ש Activity יחיד ב Workflow הסתיים – כלומר, מה השלב הבא ב workflow. המימוש הוא לרוב סט חוקים פשוט או State Machine.
הקוד שמפעיל את ה workflow נקרא Workflow Starter.
דוגמה ל workflow פשוט של עיבוד תמונה: מתאימים לה את הגודל, מוסיפים כיתוב (watermark) ושולחים הודעה שהתמונה מוכנה.

הערה קטנה של מינוחים:

start_to_close_timeout – הוא פרמטר של workflow או activity, שלאוזן ישראלית ממוצעת עלול להישמע כמו “מתי מתחילים לסגור את העניינים” 🙂
בפועל מדברים על timeout נוקשה, שיעצור את ה activity/worfklow אם מרגע התחלת הפעולה (start) עד סופה (close) – היא לא הסתיימה.

באופן דומה יש timeout שנקרא schedule_to_start, שמגביל את הזמן בו workflow יכול להמתין לפני שהוא מתחיל להיות בכלל מטופל (כלומר: להמתין ב Queue לתחילת טיפול).

בתיעוד של אמזון, ניתן למצוא תיעוד ברור על קונספטים מתקדמים יותר של שירות ה SWF, כגון: markers, signals, tags ו child workflows.

בקיצור רב (רק בכדי לקבל מושג):

  • Signals מאפשרים לעדכן את ה workflow בשינוי state מעניין שהתרחש – מאז שה workflow החל לפעול.
  • tags – מאפשרים לתייג, לצורך חיפוש עתידי ב workflow history , אחר מצבים מיוחדים שה workflow הגיע אליהם.
  • Markers – מידע (או state) נוסף שה Deciders יכולים לשמור על ה workflow – לצורך ביצוע החלטות עתידיות.
  • Child Workflow – צעד בודד ב workflow, פותח workflow משל עצמו. הצעד ב workflow מסתיים כאשר ה child workflow הסתיים. הגיוני.
שיהיה בהצלחה!

—-

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

Webinar: Introduction to Amazon SWF

AWS in Plain English – הצעה לשמות טובים יותר לשירותים של AWS + הסבר קצר על כל שירות. אהבתי (!) אם כי דווקא ההסבר על SWF הוא לא כ”כ מוצלח לטעמי (הייתי פשוט קורא לו “Workflow Service”).

[א] “לא סביר” הוא עדיין אפשרי, כמובן.
“חוק מרפי-בענן” גורס: “כל מה שעלול להיכשל – אכן ייכשל: בסוף השבוע, בחצות, ובשיא העומס”.