לדלג לתוכן

דפוסי תקשורת בין מיקרוסרביסים - איך שירותים באמת מדברים אחד עם השני

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

הציר המרכזי - סינכרוני מול אסינכרוני

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

תקשורת סינכרונית - קריאות ישירות

בגישה הזאת, שירות A קורא לשירות B ומחכה לתשובה שלו, בדרך כלל דרך REST או gRPC. זו הדרך הכי טבעית ואינטואיטיבית לחשוב על תקשורת - זה בדיוק כמו קריאה לפונקציה רגילה, רק שהיא רצה בשרת אחר.

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

תקשורת אסינכרונית - הודעות ואירועים

בגישה הזאת, שירות A לא קורא ישירות לשירות B. הוא שולח הודעה לתור או מפרסם אירוע, וממשיך הלאה מיד, בלי לחכות. שירות B מטפל בהודעה מתי שהוא מוכן, בקצב שלו. זה הדפוס שעומד מאחורי כלים כמו Kafka או RabbitMQ.

היתרון כאן הוא ניתוק אמיתי (decoupling) - שירות A לא נופל אם שירות B איטי או זמנית לא זמין, ההודעה פשוט מחכה בתור. החיסרון הוא שהזרימה קשה יותר לעקוב אחריה, ויש עיכוב מובנה בין השליחה לטיפול - עקביות סופית (eventual consistency) במקום תשובה מיידית.

מתי כל אחד מהם מתאים

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

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

דפוס ביניים - בקשה-תשובה על גבי הודעות

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

הטעות הנפוצה - לבחור דפוס אחד לכל המערכת

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

מה קורה כשקריאה סינכרונית נכשלת

בכל תקשורת סינכרונית בין שירותים חייבים לתכנן מראש מה קורה כשהצד השני לא עונה - timeout, ניסיון חוזר (retry) עם המתנה גדלה בין ניסיון לניסיון, ומנגנון שמונע מקריאות חוזרות להעמיס עוד יותר על שירות שכבר קורס (circuit breaker). בלי המנגנונים האלה, כשל בשירות אחד יכול להתפשט ולהפיל שירותים נוספים שתלויים בו, בדיוק כמו אפקט דומינו.

איפה לומדים לתכנן את זה נכון

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

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

הצטרפו לקהילה בדיסקורד

לסיכום

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