Consumer - Kafka - קפקה - הרצאה 5 מתוך 5

פורסם: 30 בנובמבר 2019

תקציר

קונסיומר: Kafka Clients, Bootstrap Servers, Deserializers; Subscribe (כולל Regex) מול Assign לפרטישנים ספציפיים; Poll loop ורכיבים פנימיים; סינכרון Thread אחד. ניהול אופסטים — Last Committed מול Current Position; Auto Commit מול Manual (commitSync / commitAsync / callback); __consumer_offsets. Consumer Groups, Group Coordinator, Rebalance; סיום סדרת הקפקא.

האזנה ישירה

תמלול הפרק (לחצו לפתיחה)

קפקא פרק 5 - הקונסיומר (Consumer) וניהול אופסטים

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

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

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

Key Deserializer & Value Deserializer: המידע בקפקא עובר בצורה בינרית (מקודד). הפרודוסר מבצע סריאליזציה (Serialization) לפני השליחה, והקונסיומר חייב להשתמש ב-Deserializer המתאים כדי להפוך את המידע הבינרי חזרה לטקסט או אובייקט שניתן להשתמש בו.

איך נרשמים להודעות? (Subscribe vs Assign)

יש לנו שתי דרכים להגדיר מה מעניין את הקונסיומר:

דרך א': Subscribe (סבסקרייב): אנחנו נרשמים לטופיק או לרשימת טופיקים. ניתן להשתמש גם בביטוי רגולרי (Regex). למשל, אם נרצה לקרוא מכל הטופיקים שמסתיימים במילה ready (כמו "מכוניות מוכנות", "עגלות מוכנות"), נוכל להשתמש בביטוי רגולרי. היתרון הוא שזה דינמי – אם יתווסף טופיק חדש עם המילה ready, הקונסיומר יתחיל לקבל ממנו הודעות אוטומטית. כשמשתמשים ב-Subscribe, הקונסיומר נרשם לכל הפרטישנים של אותו טופיק.

דרך ב': Assign (אסין): כאן אנחנו לא נרשמים לטופיק שלם, אלא לרשימה ספציפית של פרטישנים (למשל: "פרטישן 0 ו-2 של טופיק א'").

היתרון: דיוק ויעילות בביצועים.

החיסרון: אנחנו צריכים לתחזק את זה ידנית. אם נוספו פרטישנים חדשים לטופיק, לא נקבל אותם אוטומטית. בנוסף, שימוש ב-Assign גורם לנו לאבד את היכולת להשתמש ב-Consumer Group (מושג שנלמד בהמשך).

מנגנון ה-Poll (פול)

הירשמות (Subscribe/Assign) היא רק הכנה. כדי באמת לקבל הודעות, הקונסיומר משתמש במתודת ה-Poll. הפעולה הזאת צריכה לקרות בתוך לולאה (Poll Loop) שרצה כל הזמן. המתודה מקבלת ערך במילי-שניות (Timeout) – כמה זמן להמתין למידע לפני שחוזרים.

רכיבים פנימיים בקונסיומר:

Subscription State: מחזיק את רשימת הטופיקים והפרטישנים שהקונסיומר רשום אליהם.

Fetcher: מנהל את ה"לוגיקה" של התקשורת (למי פונים ומתי).

Consumer Network Client: הרכיב שמבצע פיזית את התקשורת מול הקלאסטר ומקבל את ההודעות וה-Heartbeats.

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

ניהול אופסטים (Offset Management)

זהו אחד הנושאים הכי משמעותיים. נבדיל בין שני מושגים:

Last Committed Offset: ההודעה האחרונה שהקונסיומר "אישר" שהוא סיים לטפל בה.

Current Position: ההודעה האחרונה שהקונסיומר משך מהטופיק (אבל אולי עוד לא סיים לעבד).

Auto Commit (התנהגות ברירת המחדל):

קפקא מנהלת את האופסט עבורנו (בזכות המשתנה enable.auto.commit=true). היא משתמשת באינטרוול של 5 שניות (auto.commit.interval.ms=5000). זה אומר שכל 5 שניות קפקא מניחה שהודעות שנלקחו כבר עובדו ומעדכנת את האופסט.

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

Manual Commit (שליטה ידנית):

ניתן לבטל את ה-Auto Commit ולנהל את האופסט בעצמנו:

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

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

Async with Callback: פשרה בין השתיים – ממשיכים לעבוד אבל מגדירים קוד שירוץ כשהאישור מהקלאסטר יגיע.

כל האופסטים נשמרים בטופיק פנימי מיוחד של קפקא שנקרא __consumer_offsets.

Consumer Group (קונסיומר גרופ)

מה קורה כשקונסיומר אחד לא עומד בעומס? אנחנו מייצרים קבוצה.

דוגמה: במפעל מכוניות, במקום שקונסיומר אחד יצבע את כל המכוניות, נגדיר קבוצה של 10 קונסיומרים. כל אחד מהם יקבל חלק מההודעות (מכוניות) והם יחלקו את העבודה ביניהם.

ה-ZooKeeper ממנה מנהיג לקבוצה (Group Coordinator) שדואג לחלק את העומס שווה בשווה.

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

סיום הקורס

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

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

תודה שהקשבתם, נתראה בהרצאה הבאה!