מדוע WebSocket scraping נשבר בעומסי שיא
בשוק רגוע זרימת העסקאות אחידה, ו-WebSocket scraping נראה טריוויאלי: נרשמים לערוצים, כותבים לבסיס הנתונים. הכשל מגיע בהתפרצות — הבורסה תחת עומס סוגרת חיבורים, ומגבלות החיבורים אינן מאפשרות להחזיק ערוץ נפרד לכל זוג מסחר.
נתק בחיבור לבורסה הוא מצב עבודה, לא תקלה. בזמן שהלקוח מתחבר מחדש, מאות אירועים עוברים בערוץ: נוצר פספוס של עסקאות, וספר הפקודות נבנה מתמונת מצב מיושנת ומשינויים טריים — אי-סנכרון של ספר הפקודות, שבו המחיר המחושב סוטה מהמחיר האמיתי. המסוכן מכל הוא שהסטייה אינה בולטת לעין: המספרים נראים סבירים.
צרה נפרדת — רשומות כפולות. לאחר הניתוק חלק מההודעות מגיעות שוב, ובלי דה-דופליקציה לפי מזהה האירוע הנפח בבסיס הנתונים גדל, והאגרגטים של נפח המסחר מנופחים. השגיאה מצטברת בשקט וצפה כבר באנליטיקה, בדיווח או במודל הסיכון, שם אין לה מקום.
מפרקים כיצד זה נסגר: שחזור תמונת מצב של ספר הפקודות עם בדיקת סכום ביקורת, חציצה של אירועים בזמן הניתוק, דה-דופליקציה לפי מפתח ופיזור המנויים כך שלא יישאר מה שיתקל במגבלות החיבורים.
מה נותן זרם נתונים רציף מהבורסות והרשתות
זרם רציף של ציטוטים במקום סקירה לפי לוח זמנים מסיר את הבעיה המרכזית — תנועת המחיר בין השאילתות. כשהמנוי פעיל באופן קבוע, כל שינוי בספר הפקודות וכל עסקה מגיעים ברגע התרחשותם, ושיעור האירועים האבודים נמדד בעשיריות האחוז, לא באחוזים.
ב-Binance ובפלטפורמות גדולות אחרות הזרם נמסר דרך שער עם מגבלה על מספר המנויים בו-זמנית — דווקא מגבלה זו מגדירה את ארכיטקטורת האספן, ולא גודל השוק.
נתק בחיבור הוא מצב שגרתי, לא תקלה: המגבלה מופעלת, מפתח הגישה מתחלף, קטע ברשת נופל. ההבדל ההנדסי הוא אם הזרם מתרומם מעצמו ומאיזו נקודה.
אנו שומרים את המזהה של האירוע המאושר האחרון ולאחר התחברות מחדש משלימים את הקטע שהוחמץ מההיסטוריה — זמן שחזור החיבור מתקצר לשניות בודדות, לא נדרש מפעיל, והכפילויות נחתכות לפי מפתח העסקה.
שלמות היסטוריית העסקאות נבדקת בהצלמה מול מקור בלתי תלוי: תמונת מצב של הספר ויומן ארכיון משמשים כאמת מידה, והסטייה נסגרת בחלון השלמה. ההיסטוריה נשארת ניתנת לשחזור — לפיה מחושבות מטריקות בדיעבד, כולל דקות שבהן האספן שתק.
השהיית האספקה צריכה להיות צפויה: חשוב לא הממוצע אלא הזנב — עם גידול במספר הכלים הוא לא אמור להתרחב. העומס על האספן גדל ממספר המנויים, לא מפעילות השוק: חלוקת הכלים לקבוצות בלתי תלויות, כתיבת אירועים בקבוצות ושלוחה עם לחץ נגדי שומרים על צריכה אחידה. לכן הזרם מתרחב לזוגות ולרשתות חדשים בלי לעבד מחדש את הליבה — מתווסף סגמנט נוסף, לא אספן שני.
השוואת מצבי איסוף נתוני שוק
עבור נתוני שוק אין מצב איסוף «נכון» אחד: את הסכימה בוחרים לפי מה קריטי יותר — מהירות התגובה לאירוע או שלמות ההיסטוריה לתקופה. מנוי קבוע נותן תגובה ברגע התרחשות האירוע, אך אינו שורד נתק בחיבור; סקירה תקופתית עמידה בפני ניתוקים, אך מפגרת ונתקלת במגבלות השאילתות של הבורסה. להלן ארבע אפשרויות, שביניהן בוחרים בפועל בתחילת הפרויקט.
| אפשרות | מתי מתאימה | מגבלות |
|---|---|---|
| מנוי קבוע לזרם (WebSocket) | ספר פקודות חי, פיד עסקאות, תגובה לאירוע מיד עם הפרסום | נתק בחיבור יוצר פספוסים היסטוריים: בלי נקודות ביקורת והרשמה מחדש נכונה חלק מהאירועים אובד ללא תקנה |
| סקירה תקופתית | מטריקות נדירות, מזהי כלים, הצלמת מצב לפי לוח זמנים | השהיה בין שאילתות, מגבלות קצב, עם גידול במספר הכלים גדל גם מספר הפניות |
| סכימת איסוף היברידית | מערכות מסחר ואנליטיקה, שבהן נדרשים גם מהירות וגם שלמות היסטוריה | דורשת הלחמה אידמפוטנטית: דה-דופליקציה, שמירת נקודות ביקורת, יישוב פערים בין מקורות |
| צומת רשת עצמאי | נדרשים נתונים שספקים ציבוריים אינם מוסרים: mempool, יומני חוזים מלאים ברשתות EVM | סנכרון ואחסון מצב, עדכונים ותורנות, אך אין מגבלות של אחרים ואין נקודות כשל חיצוניות |
בפועל הצירוף העובד הוא מנוי קבוע לזרם בתוספת השלמת פספוסים לפי נקודות ביקורת; צומת רשת עצמאי מחברים במקומות שבהם המקורות הציבוריים אינם מוסרים את עומק הנתונים הנדרש.
את סט המצבים אנו מגדירים לפי המשימה ומקבעים בסכימת הנתונים לפני תחילת הפיתוח — זה זול יותר מאשר לעבד מחדש את האחסון כשמתגלים חורים בהיסטוריה.
WebSocket scraping: שלבי ההטמעה והמסירה
נתונים חיים מהבורסות ומרשתות EVM קיימים רק ברגע הפרסום: מחיר, ספר פקודות, בלוקים חדשים ויומני חוזים אינם משוחזרים בדיעבד מעצמם. חיבורים קבועים במקום סקירה תקופתית נותנים השהיה מינימלית, אך דורשים משמעת בשחזור. ההטמעה לכן נבנית סביב שני סיכונים — לאבד אירוע בנתק ולא להבחין באובדן הזה. סדר העבודות להלן.
- ניתוח המקורות. מקבעים אילו ערוצים נדרשים: עסקאות, ספר פקודות, בלוקים חדשים, יומני כתובות. עבור כל אחד מבהירים את המגבלות על מספר המנויים בו-זמנית ואת עומק ההיסטוריה — היכן הזרם מספק את עצמו והיכן נדרשת השלמת נתונים.
- סכימת זרמי הנתונים. מנהלים את מסלול ההודעה: מקור → מנוי → נרמול → שלוחה → אחסון → צרכן. מסמנים נקודות חציצה, כדי שהתפרצות פעילות בשוק לא תהפוך לאובדן אירועים.
- הגדרת המנויים. מגדירים מסננים, תדירות פרסום וכלל הרשמה מחדש לכל ערוץ. הצרכן מקבל את האירועים הנדרשים, ולא את כל הזרם — העיבוד נפרק בלי לאבד נתונים משמעותיים.
- טיפול בניתוקים. מתארים את ההתנהגות בעת נתק: ניסיונות חוזרים עם השהיה גדלה, בדיקת חיות החיבור, שחזור מהבלוק או מהסמן האחרון שעובד. את המוחמץ משלימים מההיסטוריה, ואת שכבר התקבל — לא מכפילים.
- בדיקת שלמות הנתונים. מצליבים את הזרם עם מקור בלתי תלוי ועם ההיסטוריה, מחשבים את הפער במספר האירועים ואת ההשהיה המקסימלית בעיבוד. הדה-דופליקציה מתבצעת לפי מזהה האירוע, לא לפי זמן ההגעה.
- מסירת הפתרון. מוסרים את קונפיגורציות המנויים, את סכימת הזרמים, את פורמטי ההודעות ואת נהלי הפעולה בעת תקלה. צוות הלקוח רואה היכן לצפות במטריקות וכיצד להרים את הזרם לאחר תקלה.
מה נשאר אצל הלקוח לאחר הטמעת הזרם
זרם על מנויי WebSocket הוא לא רק אספן עובד, אלא ערכה שצוות הלקוח נשאר איתה לבד. לכן החבילה הסוגרת כוללת קונפיגורציות, סכימות ונהלים: לפיהם אפשר להרים את הזרם מאפס, להרחיב אותו ולהעביר אותו למהנדס אחר בלי הסברים בעל פה.
- קונפיגורציית המנויים — רשימת הערוצים והכלים לכל בורסה ולרשת, עומק ההיסטוריה המבוקשת, מרווחי ההרשמה מחדש ופרמטרי ההתחברות מחדש. מנוהלת בגרסאות, שינוי מנוי אינו דורש עריכת קוד.
- סכימת הזרמים והאחסון — המסלול מנקודת הכניסה ועד לארכיון הגולמי ולשכבה האנליטית: היכן מתבצע הנרמול, אילו שדות חובה, וכיצד מתועדים הפערים בין המקורות.
- כללי גישה — תפקידים לקריאה ולניהול, סדר הנפקת מפתחות ורוטציה שלהם, הפרדה בין סביבת הייצור לסביבת הבדיקות, שלילת גישה עם החלפת עובד.
- נוהל שחזור — הפעולות בעת נתק בתקשורת או כשל בצומת: התחברות מחדש אוטומטית, השלמת הטווח המוחמץ, הפעלה מחדש ידנית ובדיקת שלמות הנתונים לתקופה.
- תיעוד האספן — מה בדיוק נאסף, אילו מטריקות נמדדות, לפי אילו סימנים ניכרת הידרדרות הזרם והיכן להסתכל בעת ניתוח אירוע.
- נוהל הוספת מקור חדש — רשימת בדיקה: במה שונה המקור בפורמט ובמגבלות, מה נבדק לפני ההפעלה, וכמה זמן תופס החיבור.
בנפרד אנו מוסרים יומן שינויים של הקונפיגורציות ודוח עומס — נראה מתי השתנו המנויים ולאיזו תוצאה זה הוביל.
מקרה בוחן: זרם מהבורסה בלי פספוסים וניתוקי חיבור
הלקוח — צוות מסחר שאסף עסקאות ושינויים בספרי הפקודות ממספר פלטפורמות לצורך אותות ואנליטיקה היסטורית. הזרם מ-Binance נאסף בסקירות תקופתיות: בשוק רגוע זה נראה עובד, אך בהתפרצויות תנודתיות חלק מהאירועים לא נכנסו למדגם, והאספן קרס עקב שגיאת רשת והמתין להפעלה מחדש ידנית.
קיבענו את המטריקות לפני העבודות, העברנו את האיסוף לחיבור WebSocket קבוע והשווינו את המדדים לאחר מכן.
| מדד | לפני | אחרי |
|---|---|---|
| שיעור האירועים המוחמצים | עד 1.8% בהתפרצויות | מתחת ל-0.01% |
| זמן השבתת האספן | עד 40 דקות ביממה | שניות להתחברות מחדש |
| הפעלות מחדש ידניות | 6–8 ביממה | 0 |
| שלמות ההיסטוריה המשוחזרת | 92% | 100% |
בפנים, במקום סקירה לפי לוח זמנים — חיבור ארוך-טווח עם מנוי לערוצים הנדרשים ורישום כל אירוע לשלוחה על הדיסק עד לאישור העיבוד.
שתיקת החיבור מזוהה לפי היעדר אותות חיים, והנתק נסגר בהתחברות מחדש עם השהיה גדלה ובהשלמת הטווח המוחמץ מהיסטוריית הבורסה: המזהה המאושר האחרון של האירוע נשמר, ולכן חלון ההשלמה ידוע במדויק. הכתיבה אידמפוטנטית — השלמה חוזרת אינה יוצרת כפילויות.
התוצאה: היסטוריה בלי חורים מתאימה גם לאנליטיקה וגם לבדיקת אסטרטגיות על נתוני עבר, והתורן כבר אינו עוקב אחרי חיות האספן. הצלבת חתכים יומיים מול נתוני הבורסה נותנת פער בגבולות העיגול, בעוד שלפני כן החורים התגלו רק לאחר שהמודל כבר התאמן על נתונים חלקיים.
במה נבדל מנוי לזרם מסקירה תקופתית?
סקירה תקופתית — הלקוח עצמו שולח שאילתה אחת למרווח נתון לגבי המצב: רשימת פקודות, עסקאות טריות, יתרה. מיושמת באופן טריוויאלי, אינה דורשת החזקת חיבור, ולכן לרוב נשארת ערוץ גיבוי. המחיר הוא ההשהיה: האירוע נכנס למערכת לא לפני המחזור הבא, וכל מה שאירע בין שתי תמונות מצב הולך לאיבוד.
מנוי לאירועים דרך WebSocket הופך את הסכימה: החיבור נפתח פעם אחת, והמקור עצמו שולח הודעה ברגע השינוי — הופעת הזמנה, ביצוע עסקה, יציאת בלוק חדש. מהירות התגובה נקבעת לפי זמן העברת האות, ולא לפי מחצית מרווח הסקירה. עבור ארביטראז' ותגובה לחיסולים ההבדל עקרוני.
העומס על המקור בנוי אחרת. הסקירה יוצרת זרם אחיד של שאילתות ללא תלות בפעילות השוק: בשקט כמעט כולן מחזירות תשובה ריקה, אך המכסות והמגבלות מתכלות. זרם המנויים מתאים את עצמו לפעילות — התפרצות מייצרת הודעות רבות, בשקט הערוץ שותק.
שלמות התמונה — קו פרשת המים השני. הסקירה מחזירה תמונת מצב, והזמנה שהוגשה ובוטלה בתוך החלון לא תופיע בנתונים כלל. הזרם שומר על רצף האירועים, אך דורש טיפול בניתוקים: בהתחברות מחדש המוחמץ מושלם בנפרד, וספר הפקודות המקומי משוחזר — אחרת התמונה תחרוג מזו של הבורסה.
לכן את השיטות לא מעמידים זו מול זו אלא משלבים: המנוי מחזיק את הזרם, וסקירה נדירה מצליבה את המצב ותופסת פערים. מפרקים כיצד זה נבנה למשימה מסוימת.
ספקות טכניים לפני תחילת העבודות
ספקות בתחילת הדרך נוגעים לעיתים רחוקות לארכיטקטורה — לרוב הם עוסקים בשאלה כיצד האספן החדש מסתדר עם הקו הקיים ומי אחראי לאירועים. להלן שאלות שנשאלות לפני חתימה על תוכנית העבודה.
אצלנו כבר פרוס אספן — להתחיל מאפס?
מתחילים בביקורת: בוחנים אילו זרמי נתונים כבר פועלים, היכן הולכות לאיבוד הודעות וכיצד מטופלים ניתוקי חיבור. לרוב משתלם יותר להשלים נרמול והשלמת היסטוריה לצד הקו הקיים ולהחליף מקורות בזה אחר זה. האספן הישן פועל כעתודה, עד שהנתונים יתכנסו בהצלבת בדיקה.
כיצד לא להיתקל במגבלות המקור?
מגבלות המקור הן הגבלה על מספר המנויים הפעילים ועל תדירות ההרשמות מחדש. המתזמן שומר מרווח בזרמים, מפזר אותם בין חיבורים, וכשהמגבלה מופעלת נותן עדיפות לכלים ולרשתות קריטיים, ואת השאר שם בתור. לאחר נתק האספן משחזר את המצב מתמונת המצב הקרובה ומשלים את המוחמץ, ולא מתחיל מאפס.
מי אחראי לתקלות בצד הבורסה?
אנו אוספים טלמטריה עבור כל מקור: השהיית האספקה, תדירות הניתוקים, פער הדלתאות מול תמונת המצב. אם התקלה מאומתת בצד המקור — זהו אירוע חיצוני, ואנו מתעדים אותו בנפרד משגיאות הקו שלנו. השחזור אוטומטי: התחברות מחדש, הרשמה מחדש, השלמת היסטוריה.
כיצד להרחיב את רשימת הרשתות והפלטפורמות?
כל מקור חדש מתחבר באמצעות מתאם נפרד: סכימת מנוי משלו, התאמה למודל נתונים משותף, הפעלה מאחורי דגל. מקורות שכבר פועלים אינם נגעים — הרחבת הרשימה אינה יוצרת סיכון לאיסוף הנוכחי.
מה כלול בהעברת הידע?
סכימות של זרמים ומנויים, קונפיגורציות, נוהל תורנות וניתוח אירועים, ודיון עם הצוות שלכם על תקלות אמיתיות. לאחר המסירה תוכלו להוסיף מקורות ולשנות סדרי עדיפויות בלעדינו.
נדון במשימה ונחזור עם הערכה ותוכנית
כדי שהשיחה תהיה עניינית, די לשלוח את מה שכבר קיים: רשימת הבורסות והרשתות שצריך לכסות, ואילו נתונים נדרשים מכל אחת — עסקאות, ספר פקודות, סטטוסים של טרנזקציות, אירועי חוזים.
הוסיפו את תדירות העדכון, את עומק ההיסטוריה הנדרש ואת היעד שאליו התוצאה צריכה להגיע: לבסיס נתונים, לשלוחה או ישירות לשירות שלכם.
בתגובה מגיע ניתוח מפורט לפי סעיפים, שעל פיו כבר אפשר לקבל החלטה.
- הגדרת המשימה — אילו זרמים ומאילו פלטפורמות אנו מרימים, מה נחשב למקור האמת, והיכן אובדן אירועים מותר והיכן לא.
- סכימת הפתרון — כיצד בנויים החיבורים, ההרשמה מחדש לכלים והשלמת הקטע המוחמץ לאחר נתק בתקשורת.
- תוכנית שלבים — במה מתחילים, איזו תוצאה ביניים נחשבת עובדת, ובאיזה שלב יוצאים לבדיקה בנתונים אמיתיים.
- הרכב הארטיפקטים — שירותים, קונפיגורציות, סכימת הזרמים והאחסון, הוראות הפעלה, סט מטריקות ולוגים.
- קריטריוני קבלה — רציפות הזרם תחת עומס, ההתנהגות בעת נתק, שלמות הנתונים ההיסטוריים, הפער מול נתוני הבורסה.
- גבולות העבודה — מה אנחנו מכסים, מה נשאר בצד שלכם ואילו תלויות חיצוניות משפיעות על לוחות הזמנים.
את הסט הזה נוח להשתמש בו גם כרשימת בדיקה בבחירת ספק: אם בתגובה אין סכימה, שלבים ונוהל בדיקה — אין מה להעריך.







