איך להתמודד עם backpressure כשמערכת יעד איטית מהמערכת השולחת
אינטגרציות · אוקטובר 2026
מדריך לניהול backpressure באינטגרציה: גבולות תור, ויסות קצב, concurrency, עדיפויות, retries, מניעת כפילויות והתאוששות מבוקרת.
קטגוריה: אינטגרציות | תאריך: אוקטובר 2026
מערכת מקור יכולה לייצר בקשות, אירועים או קבצים מהר יותר מכפי שמערכת היעד מסוגלת לעבד. בתחילת היום הפער קטן, אבל בשעת עומס התור מתארך, זמני התגובה עולים, retries מוסיפים עוד עבודה ובסוף משתמשים אינם יודעים אם הבקשה ממתינה, נכשלה או בוצעה פעמיים.
זהו מצב של backpressure: קצב הכניסה גבוה מקצב העיבוד לאורך זמן. הפתרון אינו רק להוסיף עוד workers. צריך לקבוע כיצד מווסתים את הזרימה, כמה עומס מותר לצבור, אילו בקשות קודמות לאחרות ומה עושים כאשר אי אפשר לעמוד בקצב בלי לפגוע במערכת היעד.
מה ההבדל בין עומס רגעי ל-backpressure?
עומס רגעי הוא קפיצה שהמערכת יכולה לספוג ולהשלים אחר כך. Backpressure מתחיל כאשר הפער בין קצב הכניסה לקצב היציאה ממשיך להצטבר.
כדאי למדוד לפחות ארבעה ערכים:
- קצב כניסה: כמה פריטים מגיעים בדקה;
- קצב עיבוד: כמה פריטים מסתיימים בהצלחה בדקה;
- עומק תור וגיל הפריט הישן ביותר;
- זמן מקצה לקצה מרגע הקבלה ועד לתוצאה העסקית.
לדוגמה, אם נכנסות 600 בקשות בשעה ומערכת היעד משלימה 400, תוספת של 200 בקשות בכל שעה אינה תקלה זמנית. גם אם כל קריאה בודדת מצליחה, החוב התפעולי גדל. עומק התור לבדו אינו מספיק: 1,000 פריטים בני שתי דקות שונים מ-1,000 פריטים שממתינים מהיום הקודם.
למה retry עלול להחמיר את המצב?
כאשר מערכת יעד מאטה, timeouts ושגיאות זמניות גורמים לעיתים לכל worker לנסות שוב. כך הקצב שהיעד רואה עולה דווקא בזמן שבו הקיבולת שלו ירדה.
Retry צריך להיות חלק ממדיניות עומס:
- backoff מדורג עם jitter כדי למנוע גל ניסיונות מסונכרן;
- מגבלה על מספר הניסיונות ועל הזמן הכולל לטיפול;
- הפרדה בין שגיאה זמנית לשגיאה עסקית שלא תיפתר בניסיון נוסף;
- כיבוד Retry-After או אות עומס מוסכם כאשר היעד מספק אותו;
- מעבר למסלול חריגים לאחר מיצוי המדיניות.
המדריך על retry וכשלונות באוטומציה מפרט את מדיניות הניסיונות. בהקשר של backpressure חשוב לזכור ש-retry מתחרה בבקשות חדשות על אותה קיבולת.
להפריד בין קבלה לבין ביצוע
אם המשתמש חייב להמתין עד שכל מערכות היעד מסיימות, האטה ברכיב אחד עוברת מיד לכל המסלול. במקרים שבהם התהליך העסקי מאפשר זאת, אפשר להפריד:
- לקבל את הבקשה ולבצע ולידציה בסיסית.
- להקצות מזהה מעקב ולשמור אותה בצורה עמידה.
- להחזיר למקור סטטוס "התקבלה לעיבוד" ולא "הושלמה".
- לעבד בקצב שמגן על מערכת היעד.
- לעדכן סטטוס סופי או חריג באופן שניתן למעקב.
הפרדה זו אינה מתאימה לכל פעולה. בדיקת יתרה לפני אישור עסקה, לדוגמה, עשויה לדרוש תשובה מיידית. אך יצירת משימת המשך, סנכרון קטלוג או קליטת מסמך יכולים לעיתים לעבור למסלול אסינכרוני.
הבחירה בין חלונות עיבוד לבין זרימה רציפה משפיעה גם על צורת ספיגת העומס; המדריך על batch לעומת עיבוד רציף מסביר כיצד לקשור את ההחלטה לדחיפות, לנפח וליכולת ההתאוששות.
אסור לטשטש את המשמעות למשתמש. 202 Accepted או הודעת "נקלט" אינם אישור שהעדכון בוצע במערכת היעד. המסך, ה-API והלוגים צריכים להבחין בין התקבל, ממתין, בעיבוד, הושלם ונכשל.
לקבוע גבול לתור
תור בלתי מוגבל אינו מנגנון הגנה. הוא רק דוחה את הכשל וצובר עבודה שעלולה להיות ישנה או לא רלוונטית.
מגדירים מראש:
- מספר פריטים או נפח מרבי;
- גיל מרבי לבקשה לפני בדיקה או ביטול;
- מגבלת אחסון לקבצים ול-payloads גדולים;
- סף אזהרה וסף קריטי;
- מה קורה כאשר הגבול הושג;
- מי מוסמך לשנות את הגבול ובאילו תנאים.
כאשר התור מלא, האפשרויות כוללות דחייה מפורשת, האטת הקבלה, מעבר לקליטה בקובץ, שמירת בקשה במערכת המקור או קבלת סוגי בקשות קריטיים בלבד. הבחירה היא עסקית ולא רק טכנית: עדיף להחזיר תשובה ברורה מאשר לקבל עבודה שאין סיכוי סביר להשלים בזמן הנדרש.
לווסת קצב לפי קיבולת אמיתית
Rate limiter בצד השולח צריך לשקף את הקיבולת של היעד ולא רק את מגבלת ה-API הרשמית. יעד יכול לאפשר מספר קריאות גבוה אך לעבד סוג פעולה כבד בקצב נמוך יותר.
אפשר להשתמש בשילוב של:
- מגבלת concurrency על מספר פעולות פעילות;
- token bucket או מכסה לכל חלון זמן;
- קצב נפרד לכל endpoint או סוג פעולה;
- הגבלה לפי tenant, יחידה עסקית או מערכת מקור;
- התאמה דינמית לפי latency, שיעור שגיאות ואותות מהיעד.
שינוי דינמי צריך להיות מוגבל וזהיר. אם כל ירידה קצרה ב-latency מגדילה מיד concurrency, המערכת עלולה להתנדנד בין הצפה לעצירה. קובעים מינימום, מקסימום, חלון מדידה ושינוי הדרגתי.
כאשר קיימות מגבלות קצב API, מחלקים את התקציב בין תהליכים וצרכנים. Backpressure מוסיף את שאלת הקיבולת בפועל ואת ניהול ההצטברות כאשר הקצב המותר אינו מספיק לביקוש.
לתעדף לפי ערך עסקי וגיל
FIFO הוא ברירת מחדל פשוטה, אך לא תמיד נכונה. בקשת ביטול דחופה עלולה להמתין מאחורי אלפי עדכוני קטלוג, ופעולה קצרה יכולה להיתקע מאחורי batch כבד.
אפשר להגדיר תורים או מכסות נפרדות עבור:
- פעולות משתמש אינטראקטיביות מול עבודות רקע;
- בקשות ביטול או תיקון מול קליטה שגרתית;
- לקוחות או יחידות עם חלון תפעולי מוגדר;
- פעולות קצרות מול פעולות כבדות;
- עבודה חדשה מול backlog ישן.
תעדוף חייב להיות גלוי ומוגבל. אם תמיד נותנים קדימות לעבודה חדשה, פריטים ישנים עלולים לא להתבצע לעולם. אפשר להוסיף aging שמעלה בהדרגה את העדיפות של פריט ממתין, או לשמור אחוז קיבולת קבוע לניקוי backlog.
להחליט מתי לדחות, להשהות או להשיל עומס
כאשר הקיבולת אינה מספיקה, המערכת צריכה לבחור במפורש:
האטת המקור
אם המקור נשלט, אפשר להקטין batch, להגדיל מרווח בין שליחות או לעצור משימה מתוזמנת. זו האפשרות הישירה ביותר כי היא מונעת הצטברות נוספת.
דחייה עם תשובה ברורה
API יכול להחזיר שגיאת עומס זמנית עם זמן ניסיון מומלץ. המקור צריך לכבד את ההנחיה ולא לבצע loop מהיר.
השהיית עבודה לא קריטית
סנכרון, העשרה או דוחות שאינם דחופים יכולים להיעצר כדי לשמור קיבולת לפעולות מרכזיות. נדרש מנגנון חידוש ובדיקת פערים.
השלת עומס
לעיתים מותר לוותר על פריטים שניתן לייצר מחדש, כמו רענון cache או מדד רגעי. אסור להחיל זאת אוטומטית על פקודה עסקית, מסמך או עדכון שמחייב עקיבות.
מעבר למצב מוגבל
אפשר לקבל בקשות לצפייה אך לא לעדכון, לקלוט בקשות בלי לבצע אותן מיד, או לאפשר רק פעולות בעלות עדיפות גבוהה. המשתמשים צריכים לראות שהשירות במצב מוגבל ומה המשמעות של הפעולה שלהם.
למנוע כפילויות בזמן האטה והתאוששות
ככל שההמתנה ארוכה יותר, גדל הסיכוי שמקור ישלח שוב כי לא קיבל תשובה. כל פעולת כתיבה צריכה זהות עסקית או מפתח idempotency שמאפשר לזהות ניסיון חוזר.
יש להחליט:
- כמה זמן נשמר מפתח הבקשה;
- האם ניסיון חוזר מחזיר את התוצאה הקודמת או את הסטטוס הנוכחי;
- מה קורה אם אותו מפתח מגיע עם payload שונה;
- כיצד מזהים בקשה שנקלטה אך עדיין לא בוצעה;
- האם replay של backlog מפעיל שוב side effects.
המאמר על מניעת עיבוד כפול באמצעות idempotency מרחיב על תכנון המפתח ושמירת התוצאה.
לתכנן התאוששות בלי ליצור גל נוסף
כאשר מערכת היעד חוזרת לפעול, לא שולחים אליה מיד את כל התור. Recovery burst יכול להפיל אותה שוב.
תהליך חזרה מבוקר כולל:
- בדיקת חיבור ופעולה בטוחה אחת.
- פתיחת הקצב בהדרגה.
- חלוקת קיבולת בין בקשות חדשות ל-backlog.
- ניטור latency, שגיאות וגיל התור.
- עצירה או הקטנת קצב אם המדדים מחמירים.
- reconciliation לאחר השלמת הפער.
אם סדר הבקשות משמעותי, יש לשמור סדר לפי ישות או מפתח עסקי ולא בהכרח סדר גלובלי. אפשר לעבד לקוחות שונים במקביל אך לשמור סדר עדכונים עבור אותו לקוח.
מדדים והתראות שמייצגים את התהליך
CPU של worker או זמינות queue אינם אומרים אם בקשות עסקיות מתקדמות. לוח בקרה שימושי כולל:
- קצב כניסה, הצלחה, כשל ו-retry;
- עומק תור לפי סוג ועדיפות;
- גיל הפריט הישן ביותר ואחוזונים של זמן המתנה;
- מספר פעולות פעילות ו-concurrency בפועל;
- latency ושיעור שגיאות של מערכת היעד;
- פריטים שנדחו, הושהו או הועברו לחריגים;
- זמן צפוי לניקוי backlog בקצב הנוכחי;
- פער בין "התקבל" לבין "הושלם" לפי תהליך.
התראה צריכה לשלב גודל וגיל. תור גדול שמתרוקן במהירות עשוי להיות תקין; תור קטן עם בקשה אחת קריטית שממתינה שעות דורש טיפול.
מסלול טיפול תפעולי
לפני הייצור מתעדים playbook קצר:
- כיצד מזהים אם הבעיה במקור, בתור, ב-worker או ביעד.
- מי יכול להקטין או להגדיל קצב.
- אילו סוגי עבודה מותר להשהות.
- כיצד מודיעים למשתמשים על עיכוב.
- איך מעבירים פריט למסלול חריגים.
- איך מחזירים פריט מתוקן בלי לעקוף idempotency.
- כיצד בודקים שה-backlog נוקה ושאין פער עסקי.
פריטים שמיצו retries אינם צריכים להישאר לנצח בראש התור. Dead-letter queue מאפשר להפריד חריגים, לחקור אותם ולהחזירם בצורה מבוקרת.
איך לבדוק backpressure לפני ייצור
בדיקה שימושית אינה חייבת לשחזר את כל נפח הייצור. אפשר לבנות POC ממוקד:
- לבחור flow אחד עם מקור ויעד מוגדרים.
- למדוד קצב רגיל, קצב שיא ו-latency בסיסי.
- להאט את יעד הבדיקה בצורה מבוקרת.
- להעלות את קצב המקור מעל קצב העיבוד.
- לוודא שהתור נעצר בגבול שהוגדר.
- לבדוק ש-retries אינם מציפים את היעד.
- לאמת עדיפות, סטטוסים למשתמש ומניעת כפילויות.
- להחזיר את היעד לקצב רגיל ולבחון recovery מדורג.
- לבצע reconciliation בין מה שנקלט למה שבוצע.
בבדיקה חשוב להשתמש בנתונים סינתטיים ולא לייצר פעולות עסקיות אמיתיות. אם סביבת היעד אינה מאפשרת האטה, אפשר להשתמש ב-stub שמדמה latency, שגיאות ואות עומס, אך לאחר מכן עדיין נדרשת בדיקת חיבור מבוקרת מול הסביבה האמיתית.
שאלות נפוצות
האם queue פותר backpressure?
Queue מפריד בין קבלה לעיבוד וסופג קפיצות זמניות, אך אינו יוצר קיבולת. בלי גבולות, ויסות קצב ומדיניות חריגים הוא רק צובר את הפער.
האם פשוט צריך להוסיף workers?
רק אם צוואר הבקבוק נמצא בעיבוד שבשליטתכם ומערכת היעד יכולה לקבל יותר עבודה. אם היעד הוא המגבלה, workers נוספים עלולים להגדיל concurrency, timeouts ו-retries.
מהו גודל התור הנכון?
אין מספר אוניברסלי. מחשבים לפי קצב שיא, זמן ספיגה רצוי, גודל payload, דרישת זמן עסקית ויכולת ניקוי לאחר התאוששות. הגבול צריך להיות קטן מספיק כדי למנוע חוב בלתי נשלט וגדול מספיק לספוג תנודה צפויה.
איך מעריכים מתי backlog יתנקה?
בקירוב, מחלקים את מספר הפריטים בקצב העיבוד נטו: קצב היציאה פחות קצב הכניסה החדש. אם הקצב נטו אפס או שלילי, התור לא יתנקה בלי להקטין כניסה או להגדיל קיבולת.
האם לעבד תמיד לפי FIFO?
FIFO מתאים כאשר לכל הפריטים ערך ודחיפות דומים והסדר חשוב. בתהליכים מעורבים כדאי להגדיר עדיפויות, מכסות ו-aging, תוך שמירה על סדר במקום שבו הוא בעל משמעות עסקית.
להתחיל מ-flow אחד שנחנק בשעות עומס
בחרו תהליך שבו זמני ההמתנה גדלים בשעות מסוימות או בזמן האטה של מערכת יעד. מדדו קצב כניסה, קצב יציאה וגיל תור; הגדירו גבול, concurrency ומדיניות retry; ואז בדקו האטה והתאוששות מבוקרות. המטרה הראשונה היא לא אפס תורים, אלא התנהגות צפויה: אין הצפה, אין כפילויות, המשתמש רואה סטטוס נכון והארגון יודע כיצד לחזור לקצב רגיל.
Adaptico עוסקת באינטגרציה ואוטומציה בין מערכות ארגוניות. אפשר לעיין ב[שירותי האינטגרציה והאוטומציה](/#services) או [לקבוע שיחת התאמה](/#contact) כדי למפות flow אחד ולתכנן עבורו מנגנון backpressure ו-POC ממוקד.