בוט ניטור ממפול: היכן אובדות טרנזקציות ומדוע
הממפול של Ethereum אינו רשימה גלובלית אחת של טרנזקציות ממתינות, אלא אוסף של תורים מקומיים: כל צומת מחזיק מאגר משלו בגודל מוגבל ובכללי בחירה משלו.
כאשר תור הטרנזקציות מתמלא, הצומת דוחק החוצה את הרשומות החלשות ביותר, ולכן בוט ניטור ממפול המחובר לצומת אחד רואה רק את הפרוסה שלו של האירועים.
דחיקה על רקע עמלה נראית כך: ברגע שהמאגר מתמלא, תחת הלחץ של טרנזקציות יקרות יותר נעלמת הרשומה הישנה מהתור בלי שהגיעה לבלוק. פורמלית היא לא נדחתה — היא פשוט נעלמה מהזרם.
אם הבוט נשען רק על הופעת ההאש במינוי ואינו בודק מחדש את הסטטוס הסופי, הטרנזקציה נשארת ברישום כנשלחה, וההזמנה המקושרת נתקעת.
המקור השני לאובדנים הוא ניתוק המינוי לזרם. החיבור לצומת נשבר בעת הפעלה מחדש שלו, בתקלות רשת או בהחלפת נקודת גישה, והאירועים מרגע הניתוק אובדים בשקט: המינוי משוחזר מהרגע הנוכחי.
כלפי חוץ הכול עובד, אין שגיאות בלוגים, אבל הטרנזקציות שהוחמצו מצטברות, והפער צף מאוחר יותר, כשכבר אי אפשר לשחזר את הזרם.
ב-L2 התמונה מורכבת יותר: תור קבלה משלו, ספי עמלה משלו והשהיה משלו עד להכללה בבלוק, ולכן אותה טרנזקציה מתנהגת אחרת בממפול של Ethereum וב-L2. בהמשך נפרט כיצד זה נסגר — מה לבדוק מחדש, כיצד לעבור תקלות ניתוק וכיצד להבדיל בין טרנזקציה שאבדה לבין טרנזקציה פשוט איטית.
מה נותן ניטור רציף של תור הטרנזקציות
אירוע בתור הטרנזקציות חי רגעים ספורים: עד שהמטפל מתעורר לפי לוח זמנים, ההזדמנות כבר חלפה. ניטור רציף של תור הטרנזקציות מקצר את השהיית התגובה לאירוע מעשרות שניות לעשיריות השנייה — האות יוצא ברגע הופעת הטרנזקציה, ולא במחזור הסקר הבא.
שיעור האירועים שהוחמצו מתגלה רק בזרם רציף. בסקר עם הפסקות חלק מהטרנזקציות לא נכנס לשום תמונת מצב, ואובדנים כאלה אינם נראים בלוגים: פשוט אין מה לרשום עליהם. קליטה מבוססת-אירועים עם אישור עיבוד ומסירה חוזרת שומרת על שיעור החמצות אפסי — כל כשל מסירה נרשם ומטופל.
זמן ההתאוששות לאחר תקלה נמדד לא בהפעלת התהליך מחדש, אלא בחזרה לשלמות הנתונים. התחברות מחדש אוטומטית לצומת, השלמת בלוקים שהוחמצו מנקודת ביקורת והשוואת מצב מקצרים את המסלול הזה לעשרות שניות — במקום שעות של ניתוח ידני עיוור.
אפקט נפרד הוא הסרת סוג שלם של כשלים. אין כאן עניין ב״הבוט נפל״, אלא בשירות שעובד ושותק: האירוע עבר, אין אות. דה-דופליקציה, עיבוד אידמפוטנטי וחזרה תקינה של המצב בעת ארגון מחדש של השרשרת מסירים את הסוג הזה לחלוטין: החמצה הופכת לאירוע גלוי, ולא לאובדן שקט.
מתווספת גם שליטה: מדדי התור, פיגור העיבוד, מונה הניסיונות החוזרים וסף ההתראה מראים שהניטור חי, עוד לפני שמגלים זאת דרך אירוע שהוחמץ. בתוצאה — השהיית תגובה בשברירי שנייה, שיעור החמצות כמעט אפסי, התאוששות בתוך דקה והיעדר סוג ״אירוע שהוחמץ״. כל סעיף נבדק על גבי גרף, ולא במילים.
ניטור ממפול: מצבי עבודה והמגבלות שלהם
ניטור ממפול מתחיל בבחירת מצב הניטור של הזרם: הוא זה שקובע מה הבוט בכלל מסוגל לראות, ומגבלה זו קודמת לכל לוגיקת סינון.
הטרנזקציה נעשית גלויה לצומת ברגע ההפצה ברשת, אך הופעה בזרם אינה מבטיחה לא הכללה בבלוק ולא שמירה על הסדר — חלק מהטרנזקציות מוחלפות לפי מחיר, וחלק נזרקות בעת ארגון מחדש של השרשרת.
| מצב | מתי מתאים | מגבלות |
|---|---|---|
| מינוי מלא לזרם | נדרשים כל האירועים לפני ההכללה בבלוק, כולל כאלה שלא צלחו | דורש צומת משלו עם מרווח בדיסק וברוחב הפס; בזרם יש כפילויות ורעש, והסינון נופל על הבוט |
| מעקב סלקטיבי אחר כתובות | מעניין סט מוגבל של ארנקים וחוזים | הצומת מספק רק התאמות — ההקשר סביב העסקה אינו נראה; כשהכתובות מתחלפות, הכללים נבנים מחדש |
| סקר לפי לוח זמנים | בדיקות נדירות, אין דרישות להשהיה | בין סקר לסקר אירועים אובדים, ופרצי פעילות מוחמצים כולם |
| ניטור בלוקים מאושרים | נדרשת מהימנות ודיווח, ולא מהירות | הנתונים מגיעים בהשהיה של כמה בלוקים, ותגובה לאירוע אינה אפשרית |
המצבים אינם סותרים זה את זה: מערך טיפוסי משלב מינוי מלא לאות מוקדם ובלוקים מאושרים כמקור האמת, ומעקב סלקטיבי אחר כתובות מפחית עומס כשהכתובות מעטות. טעות נפוצה היא להתייחס לזרם כמובטח: בלי טיפול בארגון מחדש של השרשרת ובהחלפת טרנזקציות, הבוט מציג אירועים שלא יהיו בהיסטוריה הסופית. לכן את מגבלות המצב מקבעים בתיאור המערך מראש, ולא אחרי הפער הראשון במספרים.
כיצד אנחנו מטמיעים את הבוט: שלבי העבודה ההנדסית
העבודה מתנהלת בשלבים — מביקורת הזרם ועד מסירת השליטה. כל שלב נסגר בתוצר שאפשר לבדוק לפני העלייה לפעולה.
- ביקורת הזרם והצומת. בוחרים מקור אירועים — נודה משלנו או ספק חיצוני, רמות אישור, אופן המינוי לבלוקים ולטרנזקציות. מודדים את עוצמת השיא ואת שיעור הרעש: מכך תלויים הספים, המגבלות והצורך במקור גיבוי.
- תרשים עיבוד האירועים. מקבעים את מסלול הטרנזקציה: קליטה, פרסור, נרמול שדות, סינון כפילויות, תור, מטפל, התראה. את המסלול החם מפרידים מהאנליטיקה, כדי שהשהיות לא יצטברו בפרצים.
- הגדרת מסננים. מרכיבים כללים לפי כתובות, חוזים, שיטות קריאה, סף gas וסוג הפעולה. עבור L2 — סט נפרד: שם סדר האירועים והאישורים שונים מהרשת הראשית. כל הפעלה נרשמת ביומן עם הסיבה, כדי שאפשר יהיה להסביר את הכלל ולכבות אותו בלי לשנות קוד.
- בדיקת עומס. מריצים זרם שיא וניתוק חיבור, בודקים אם הבוט מדביק את מה שהוחמץ, אם אין כפילויות ואובדנים, ואיך מתנהג התור. בנפרד בודקים את המעבר למקור גיבוי.
- ניתוח התראות שווא. על מדגם אמיתי מתקנים ספים ומשקלים, ומסירים רעש בלי לאבד אירועים משמעותיים. מקבעים את ההגדרה של התראת שווא, כדי שהמדד יהיה חד-משמעי.
- קבלה ומסירה. מוסרים לפי בדיקות שהוגדרו מראש, מעבירים תצורות, תרשים עיבוד, הוראות הפעלה ונוהל חזרה לאחור. בהמשך — נוהל: כיצד לשנות מסננים, לעדכן את רשימת הכתובות ומה לראות בניטור.
תצורות, תרשימים ונהלים שנשארים אצלכם
אנחנו מוסרים לא גישה לשרת, אלא ערכה שלפיה הבוט מוקם, מוגדר מחדש ומתוחזק בלעדינו. התצורות, התרשימים והנהלים נמצאים במאגר הקוד שלכם: מהנדס שלא ראה את הבוט קודם מבין אותם בתוך משמרת תורנות אחת.
- קובצי התצורה של הבוט. פרופילים נפרדים לרשת הראשית ולרשתות ה-L2 הנדרשות: כתובות צמתים, ספי גודל ועמלה, רשימות כתובות ומאגרים למעקב. שינויים — דרך משתני סביבה, בלי לשנות קוד.
- תרשים זרימות הנתונים. מסלול האירוע מהמינוי לטרנזקציות ולבלוקים חדשים ועד הסינון ושליחת ההתראה: איפה החוצץ, איפה הניסיונות החוזרים, וכיצד משלימים את הפער לאחר ניתוק החיבור לצומת.
- כללי בחירת אירועים. מטריצת תנאים: מה נכנס להתראה ומה נחסם כרעש — החלפות במאגרים מסוימים, משיכת נזילות, קריאות חריגות לחוזים, ספים לפי המשימות שלכם.
- מפת נקודות הכשל. היכן הבוט מאבד אירועים: ניתוק הזרם, ארגון מחדש של השרשרת, הצפת התור, אי-זמינות ערוץ ההתראות. לכל נקודה — סימן ופעולה של התורן.
- התראות. תבניות הודעות ומסלולים למסנג'ר או לאפיק פנימי, חלוקה לפי חומרה — בלילה מגיעים רק אירועים משמעותיים.
- תיעוד ונהלים. פריסה ועדכון, סדר תורנות, רשימת בדיקה בעת תקרית וחזרה לתצורה הקודמת.
- לוח מדדים. השהיית עיבוד האירוע, שיעור הרעש שנזרק, מספר הפערים שהוחמצו — ההידרדרות נראית לפני שהיא נעשית לבעיה.
מקרה בוחן: שיעור האירועים שהוחמצו ירד פי כמה
לפני ההטמעה הבוט סקר את הצומת לפי טיימר אחת לכמה שניות: בזמן הזה חלק מהטרנזקציות הספיק להיכנס לבלוק, והאירועים אבדו. התורן למד עליהם מהלוגים בדיעבד, ואי-התאמות ביתרות טופלו ידנית.
כל תקרית גזלה עד חצי שעה של השוואות לפי כתובות ו-nonce — בזרם של מאות טרנזקציות בדקה בדיקות כאלה אכלו משמרת שלמה.
מה שינינו
את האיסוף העברנו מסקר למינוי לזרם הטרנזקציות הנכנסות של הממפול Ethereum, חיברנו כמה צמתי-מקור בלתי תלויים ותפרנו אותם עם דה-דופליקציה לפי האש. המסנן מפרק את הנתונים לפי כתובות, חוזים וקריאות לשיטות, ולא מזרים הכול אל המטפל.
בנפרד סגרנו את העיבוד החוזר בעת ארגון מחדש של השרשרת — קודם דווקא שם אירועים אבדו ושוכפלו. ההתראה יוצאת מיד למסנג'ר של התורן ולתור השירות, ולכל אירוע יש קישור לטרנזקציה וסטטוס אישורים.
מה נהיה
מדידה על אותו זרם: שיעור האירועים שהוחמצו ירד מכמה אחוזים לשברי אחוז, הזמן מהופעת הטרנזקציה בממפול ועד ההתראה התקצר מעשרות שניות לשנייה-שתיים, והבדיקות הידניות — בערך פי עשרה.
לוגים, מדדים והתראות על אי-זמינות הצומת מרוכזים במקום אחד: אם מקור מפגר או נופל, זה נראה לפני שהאירוע יאבד. אותו מערך עובד גם עבור L2 — משתנה רק סט המקורות.
זרם טרנזקציות או בלוקים מאושרים: מה לבחור?
תשובה קצרה: אלה לא חלופות, אלא שני שכבות נתונים שונות. זרם הטרנזקציות נותן התראה מוקדמת עוד לפני ההכללה בבלוק, והבלוקים המאושרים — עמידות בפני ארגון מחדש של השרשרת. בוט שמאזין רק לממפול Ethereum מגיב מהר יותר, אבל תופס באופן קבוע אירועים שאינם בהיסטוריה הסופית.
המחיר של אות מוקדם הוא רעש. טרנזקציה מהממפול יכולה להידחק החוצה, להיות מוחלפת בגרסה עם עמלה גבוהה יותר או לא להיכנס לבלוק; בעת ארגון מחדש של השרשרת האירוע שנראה נעלם מהענף הקנוני. אם הבוט מבצע פעולה מיד, כל אי-התאמה מייצרת חזרה לאחור או כפילות.
הסתמכות רק על בלוקים מסירה את הבעיה, אבל מוסיפה השהיה: עד לעומק האישורים הנדרש חולפים כמה בלוקים. לכן בתצורה העובדת שני הערוצים חיים יחד ונבדלים בתפקיד: הזרם — אות, הבלוק — אמת.
בפועל מדובר באישור כפול של האירוע. האות הראשוני מכניס את האירוע לתור ומתחיל הכנה, והפעולה מבוצעת כשכותה הטרנזקציה נמצאת בבלוק בעומק שהוגדר. מפתח הדה-דופליקציה לפי האש, חוצץ הבלוקים האחרונים וההרצה החוזרת בעת ארגון מחדש לא מאפשרים לאירוע אחד לפעול פעמיים.
הסתעפות נפרדת היא בחירת מקור הנתונים: נודה משלנו נותנת זרם מלא ומסננים משלנו, אבל דורשת תחזוקה; ספק צד-שלישי מסיר עומס, אך מגביל את קצב הבקשות ואת עומק ההיסטוריה. עבור L2 את בדיקת העומק מגדירים בנפרד — נתוני הסקוונסר והגשר מאושרים אחרת.
ספקות ומגבלות: מה לבדוק לפני תחילת העבודה
לפני שמתחילים כדאי להפריד בין שתי שאלות שונות: כיצד הבוט מתנהג תחת עומס ומה קורה כשהוא טועה. זרם הטרנזקציות הנכנסות ברשת ציבורית Ethereum הוא עשרות אלפי אירועים בשנייה, ומינוי ״לכול״ מעמיס על הצומת יותר מהבוט עצמו.
לכן הבחירה נעשית בצד הצומת — לפי כתובות וחתימות של שיטות, ולא בסינון בתוך האפליקציה, ולניטור מוקצה צומת נפרד ולא צומת משותף עם שירותים אחרים.
סוג הסיכונים השני — החמצות ורעש. ניתוק חיבור, הפעלה מחדש או פיגור של הצומת יוצרים ״חלון עיוור״, ולכן הסימון של הבלוק האחרון שעובד וההגנה מפני חזרות נשמרים על הדיסק: אחרי ריסטארט הבוט מדביק את מה שהוחמץ, ולא מתחיל מדף חלק.
התראות שווא נוצרות מטרנזקציות שבוטלו והוחלפו ומארגון מחדש של השרשרת — אותן חוסמים לפי מספר האישורים ובדיקה חוזרת של המצב.
עד כמה זה יעמיס על הצומת שלנו?
הבחירה מתבצעת בצד הצומת, מינויים מיותרים אינם נפתחים, והפיגור מוצג במדדי הניטור. בעומס יתר הבוט מאט את הזרם, ולא צובר תור בזיכרון.
מה יקרה אחרי הפעלה מחדש או נפילה?
המצב נמצא על הדיסק, ולכן אחרי ריסטארט הבוט מדביק את הבלוקים שהוחמצו וממשיך מאותה נקודה. ההתראות אידמפוטנטיות — התראה חוזרת על אותה טרנזקציה אינה מגיעה.
כיצד נחסמות התראות שווא?
אנחנו בודקים לא את עצם ההופעה בזרם, אלא את המצב הסופי: טרנזקציות שהוחלפו, ביטולים וארגונים מחדש של השרשרת נזרקים. סף האישורים מוגדר לפי המשימה שלכם — מתגובה מיידית ועד מוגנת מפני חזרות לאחור.
אילו מגבלות נשארות באופן עקרוני?
ברשתות מהשכבה השנייה את הזרם יוצר הסקוונסר, וחלק מהטרנזקציות פשוט אינן נראות לפני ההכללה בבלוק. אנחנו מקבעים זאת בתיעוד, כדי לא להבטיח אות מוקדם מכפי שאפשרי פיזית.
מה עם התמיכה לאחר המסירה?
אנחנו מעבירים קוד מקור, תצורות, תרשים פריסה ונוהל פעולה בעת תקלות, ומקיימים הדרכה לצוות שלכם. בהמשך — תקופת ליווי מוסכמת עם נוהל תגובה.
נדון במשימה ונחזור עם הערכה ותוכנית
כדי לדון במשימה בצורה עניינית, נדרשים נתוני פתיחה על התשתית: אילו צמתים כבר הוקמו, מי מחזיק את ההרשאות אליהם, האם אתם מאזינים לממפול של הרשת הראשית ושל L2, והאם נדרש פירוק של זרמי טרנזקציות פרטיים. מכך תלוי היכן ממוקם המינוי לממפול ואיזה זרם אירועים המערך יישא בלי אובדנים.
שלחו את מה שיש בהישג יד — את השאר נדייק בשיחה.
- תרשים התשתית: צמתים משלכם או ספק, האם יש צומת ארכיון, מי מחזיק במפתחות ובהרשאות.
- רשימת הרשתות וה-L2 במערך והעדיפות ביניהן: למה מאזינים קודם ולמה אחר כך.
- מה נחשב לאירוע מטרה: טרנזקציות חדשות, החלפה לפי עמלה, העברות גדולות, פניות לחוזה — עם ספי הפעלה.
- ערוצי מסירת ההתראות וההשהיה המותרת: מסנג'ר, התראת HTTP, כתיבה למסד נתונים, דשבורד.
- עומס צפוי: מספר אירועים ממוצע בדקה, פרצי שיא, עומק שמירת ההיסטוריה.
- דרישות לעמידות: התחברות מחדש בעת ניתוק, טיפול בארגונים מחדש של השרשרת, יומן אירועים שהוחמצו.
- מי מצד הלקוח מקבל את התוצאה ולפי אילו מדדים נחשב את העבודה כהושלמה.
נחזור עם הערכה ותוכנית עבודה: שלבים, הרכב הצוות לכל שלב, לוחות זמנים ונקודות קבלה. את סדר היציאה לדרך נתאם לאחר שנסכים על תרשים האירועים והעומס.







