בפוסט הקודם כיסינו שני "שירותים אפליקטיביים" בסיסיים של 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").
[א] "לא סביר" הוא עדיין אפשרי, כמובן.
"חוק מרפי-בענן" גורס: "כל מה שעלול להיכשל - אכן ייכשל: בסוף השבוע, בחצות, ובשיא העומס".