# תקשורת בין שירותים — sync/async, API Gateway, Service Discovery📖 שיעור

## מה זה?

בשיעור הקודם פירקנו למספר שירותים לפי Bounded Context — אבל הם עדיין צריכים "לדבר" ביניהם (שירות הזמנות צריך לדעת אם המלאי מספיק). כבר יש לנו שני כלים לתקשורת: HTTP סינכרוני (מיחידת ASP.NET Core — הלקוח ממתין לתשובה) ו-Kafka אסינכרוני (מיחידת NoSQL — לא ממתינים). השיעור הזה נותן מסגרת להחליט **מתי** כל אחד, ומוסיף שני מרכיבים חדשים: API Gateway ו-Service Discovery.

## מילות מפתח שחשוב לזכור

• Synchronous Communication — הקורא ממתין לתשובה מיידית (HTTP/REST, gRPC) — מתאים כשצריך תשובה **עכשיו**

• Asynchronous Communication — הקורא לא ממתין (Kafka) — מתאים כשהפעולה יכולה "לקרות מאוחר יותר"

• gRPC — פרוטוקול תקשורת סינכרוני מהיר יותר מ-REST/JSON, מבוסס Protocol Buffers (בינארי, לא טקסט)

• API Gateway — נקודת כניסה יחידה שמנתבת בקשות מלקוחות חיצוניים לשירות הפנימי הנכון

• Service Discovery — מנגנון שמאפשר לשירות "למצוא" איפה שירות אחר רץ, בלי כתובת קבועה בקוד

```mermaid
sequenceDiagram
    participant Client
    participant Gateway as API Gateway
    participant Orders as Order Service
    participant Inventory as Inventory Service
    participant Kafka

    Client->>Gateway: POST /orders
    Gateway->>Orders: Route to the correct service
    Orders->>Inventory: GET /stock/5 (sync HTTP — needs an immediate response)
    Inventory-->>Orders: In stock: yes
    Orders->>Kafka: Publish "order-created" (async — doesn't wait)
    Orders-->>Gateway: 201 Created
    Gateway-->>Client: 201 Created
```

## הסבר עיקרי

מתי sync (HTTP/gRPC) — כשהפעולה **חייבת** תשובה לפני שאפשר להמשיך: "האם יש מלאי?" חייב תשובה מיידית לפני שאפשר לאשר הזמנה — אי אפשר "להמשיך בלי לדעת". gRPC עדיף על REST/JSON כשביצועים קריטיים (תקשורת פנימית תכופה מאוד בין שירותים) — פורמט בינארי מהיר יותר מ-JSON טקסטואלי, אך פחות "קריא לבני אדם" וגמיש מ-REST.

מתי async (Kafka) — כשהפעולה **לא** חוצצת בזרימה הנוכחית: "עדכן את שירות ההתראות שהזמנה נוצרה" לא צריך לעצור את תהליך ההזמנה עד שההתראה נשלחה בפועל — Kafka (מיחידת NoSQL) מפרסם ומתקדם הלאה. הכלל המעשי: אם התוצאה **חייבת** להשפיע על הבקשה הנוכחית — sync; אם היא "תגובה נלווית" שיכולה לקרות בהמשך — async.

API Gateway ו-Service Discovery פותרים בעיה חדשה שהפירוק יצר — בלי Gateway, לקוח חיצוני היה צריך לדעת את הכתובת המדויקת של **כל** שירות בנפרד (Orders ב-`orders.internal:5001`, Inventory ב-`inventory.internal:5002`...) — לא סביר ומסוכן לחשוף. Gateway נותן **כתובת אחת** ללקוחות, ומנתב פנימה. Service Discovery פותר בעיה דומה **בין** השירותים עצמם — כשיש כמה מופעים (Instances) של אותו שירות שעולים/יורדים דינמית (למשל בסקיילינג), Service Discovery עוקב אחרי מי זמין איפה, בלי כתובות קבועות (Hardcoded) בקוד.

## יתרונות

הבחנה ברורה sync/async מונעת עיצוב תקשורת שגוי (המתנה מיותרת, או חוסר-אמינות בפעולה קריטית); API Gateway מפשט את חוויית הלקוח החיצוני לכתובת אחת; Service Discovery מאפשר גמישות בפריסה (הוספת/הסרת מופעים) בלי לשנות קוד קורא.

## חסרונות

תקשורת sync בין שירותים יוצרת תלות זמן-אמת — אם Inventory Service איטי/למטה, Order Service נתקע; API Gateway הוא נקודת כשל יחידה (Single Point of Failure) אם לא בנוי עם חוסן מתאים; Service Discovery מוסיף רכיב תשתית נוסף לניהול.

## נקודות חשובות

• Sync (HTTP/gRPC) = תשובה מיידית נדרשת; Async (Kafka) = לא חוצץ בזרימה הנוכחית

• gRPC מהיר יותר מ-REST/JSON לתקשורת פנימית תכופה, במחיר קריאות/גמישות

• API Gateway = כתובת כניסה יחידה ללקוחות חיצוניים; Service Discovery = איתור שירותים פנימי בין שירותים

• תקשורת sync בין שירותים יוצרת תלות זמינות — כשל בשירות אחד עלול "לגרור" אחרים

## טעויות נפוצות

• להשתמש ב-sync HTTP לכל תקשורת "כי זה פשוט יותר", ולייצר שרשרת תלויות זמינות מיותרת

• לחשוף כתובות שירותים פנימיות ישירות ללקוחות חיצוניים במקום דרך API Gateway

• לקשח (Hardcode) כתובות IP/פורט של שירותים בקוד במקום Service Discovery — נשבר ברגע שמשהו זז

## סיכום

תקשורת sync (HTTP/gRPC) מתאימה כשצריך תשובה מיידית לפני שממשיכים; async (Kafka) מתאים לפעולות נלוות שלא חוצצות בזרימה. API Gateway נותן ללקוחות חיצוניים כתובת כניסה יחידה, מנתב פנימה לשירות הנכון. Service Discovery מאפשר לשירותים למצוא זה את זה דינמית, בלי כתובות קבועות בקוד. יחד עם Bounded Context מהשיעור הקודם, אלה שלושת המרכיבים שהופכים אוסף שירותים עצמאיים למערכת מיקרוסרביסים שלמה ועובדת.

## דוקומנטציה רשמית

[Microsoft Learn — Communication in a microservice architecture](https://learn.microsoft.com/dotnet/architecture/microservices/architect-microservice-container-applications/communication-in-microservice-architecture)

---

## תרגילים

### תרגיל 1 — sync מול async

**המשימה:** לרשימת פעולות (בדיקת מלאי לפני הזמנה, שליחת מייל אישור, עדכון סטטיסטיקות אנליטיות, חיוב כרטיס אשראי), סווגו כל אחת כ-sync או async, עם נימוק.

**בדיקה:** בדיקת מלאי וחיוב כרטיס = sync (חייבים תשובה מיידית); מייל וסטטיסטיקות = async (לא חוצצים).

### תרגיל 2 — תכנון Gateway

**המשימה:** תארו איך API Gateway היה מנתב שלוש בקשות שונות (`GET /orders/5`, `GET /products/10`, `POST /users`) לשירותים הפנימיים המתאימים.

**בדיקה:** לכל בקשה יש שירות יעד ברור, בלי חשיפת כתובות פנימיות ללקוח.

---

## פרויקט מסכם

**המשימה:** תכננו את שכבת התקשורת המלאה למערכת "מודיעין עסקי" (מהתרגיל של השיעור הקודם — Collector/Analyzer/Alert/Dashboard).

**דרישות:**
1. לכל זוג שירותים שצריכים לתקשר, קבעו sync או async עם נימוק
2. תכננו API Gateway יחיד שחושף רק endpoints רלוונטיים ללקוחות חיצוניים (לא את כל 4 השירותים ישירות)
3. תארו תרחיש שבו Service Discovery נחוץ (למשל Analyzer עולה בכמה מופעים לביצועים)

**בדיקה:** התכנון עקבי עם העקרונות מהשיעור — אין sync מיותר, ה-Gateway לא חושף שירותים פנימיים ישירות.

## מה בפרק הבא

בפרק הבא — **RabbitMQ**: הכרנו את Kafka כדוגמת ה-async שלנו, אבל מה קורה כשרוצים שבדיוק worker אחד מתוך קבוצה יטפל בכל הודעה, לא שכולם יקבלו שידור? RabbitMQ פותר את זה עם תור עבודות (Work Queue) ואישור (Acknowledgment) מפורש.
