Backpressure: מה קורה כשה-Consumer איטי מה-Producer

מאת צוות מדיה דיל · 01.07.2026 · טכנולוגיה · 4 דק׳

Buffer, Drop, Block, Reactive Streams, Streaming Pipelines, ו-Producer-Consumer Mismatch.

שירות שמפיק אירועים ב-10,000 בשנייה מוזרם אל consumer שמסוגל לעבד רק 2,000 בשנייה. בלי מנגנון בקרה, הפער הזה לא נעלם, הוא מצטבר איפשהו: בזיכרון של buffer שהולך ותופח עד ל-Out Of Memory, בתור שגדל בלי סוף, או בהודעות שנזרקות בלי שאף אחד יידע. Backpressure הוא המנגנון שמאפשר לצרכן איטי לאותת חזרה למפיק שיאט, לפני שהפער הבלתי נשלט הזה מפיל את כל ה-pipeline.

הבעיה: Producer מהיר מ-Consumer

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

אסטרטגיית Buffer: לספוג זמנית

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

אסטרטגיית Drop: לוותר על נתונים

כשbuffer מתמלא, אפשרות אחת היא לזרוק הודעות, drop oldest (לזרוק את הישנות ביותר) או drop newest (לסרב לחדשות), ולקבל שהמערכת תפעל עם אובדן נתונים מבוקר במקום קריסה מלאה. זו אסטרטגיה סבירה כשעדכניות חשובה יותר משלמות, למשל בזרם מדדי ניטור (metrics) שבו מדידה שהוחמצה כמעט לא משנה מול הזרם הכולל. זה בלתי קביל לחלוטין בזרם של הזמנות תשלום או אירועי audit שכל פריט בו קריטי משפטית או עסקית.

אסטרטגיית Block: להאט את המפיק

האפשרות השלישית היא לחסום את ה-producer עצמו, לגרום לו להמתין עד שלconsumer יש מקום פנוי, כך שקצב הייצור מותאם דינמית לקצב הצריכה בפועל, בלי לאבד אף הודעה. זו הגישה שreactive streams (כמו Reactive Streams API או RxJava) מיישמים באמצעות מנגנון request-n מפורש: ה-consumer מבקש כמות מוגבלת של פריטים בכל פעם, וה-producer לא שולח יותר ממה שהתבקש. המחיר הוא latency גדל ב-producer, שיכול להתגלגל אחורה לכל שרשרת השירותים שמזינה אותו.

קריטיות ב-Streaming Pipelines ו-Reactive Systems

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

שילוב עם Circuit Breaker

כשconsumer איטי מגיע למצב שבו אפילו backpressure לא מספיק, למשל כי dependency downstream שלו נופל לגמרי, משלבים Circuit Breaker שמפסיק לגמרי לנסות לקרוא לרכיב הכושל למשך זמן קצוב, במקום להמשיך לצבור בקשות תקועות. השילוב בין השניים מאפשר למערכת גם להאט בהדרגה בעומס רגיל וגם לעצור לגמרי כשיש כשל אמיתי, בלי לבלבל בין שני סוגי הבעיות השונים האלה.

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

תגיות: Backpressure · Reactive Streams · Streaming Pipeline · Producer Consumer · Buffer

← חזרה לבלוג · צור קשר