מדוע פיתוח API של בורסת קריפטו נכשל בשיאי עומס
שיא פעילות שובר לא את שכבת התצוגה, אלא את ליבת המסחר: זרימת ההזמנות והביטולים גדלה פי כמה, ספר ההזמנות נבנה מחדש בכל עדכון, והעומס על ליבת המסחר מפסיק להיות אחיד.
תור העיבוד מתארך, זמן התגובה לאישור הזמנה עולה — והראשונים שחשים בכך הם אלה שסוחרים דרך גישה תוכנתית ולא דרך טופס אינטרנטי.
התרחיש השני של כשל הוא ניתוק חיבורים. בעת פרץ הערוצים נקרעים בהמוניהם, הלקוחות עוברים להתחברות מחדש וכל אחד מבקש מחדש תמונת מצב של ספר ההזמנות והמינויים.
אם פיתוח ה-API של הבורסה אינו מפריד בין תמונת המצב לזרם השינויים לפי רצף, הלקוח מרכיב את ספר ההזמנות מחלקים לא אחידים: חלק מהרמות מיושנות, חלק הגיעו פעמיים, והרובוט המסחרי מקבל החלטה על בסיס תמונה לא מהימנה ומחמיר את העומס בחזרות.
היקר ביותר הוא חוסר סנכרון בין היתרות ליומן הפעולות. כאשר חיוב, זיכוי ורישום ביומן אינם קשורים בטרנזקציה אחת, או שחזרה על בקשה יוצרת פעולה שנייה, היתרה בממשק אינה תואמת את היתרה בפועל.
מכאן מתחילים בירורים ידניים של תקלות: התאמות לפי קבצי ייצוא, חסימת משיכות, אובדן אמון המשתמשים — בעוד שפורמלית כל מטפל בודד פעל ללא שגיאה.
הנקודה הרביעית היא הידרדרות ביצועים, לא כשל. הליבה חיה, אך מגיבה לאט יותר ויותר, ולא ברור היכן הגבול: אין הפרדה בין זרמים לקריאת ספר ההזמנות לבין ביצוע עסקאות, אין מגבלות על תדירות הבקשות, אין תור עדיפויות לביטולים. נבחן היכן בדיוק אובדת היציבות בשיאי עומס וכיצד סוגרים זאת ברמת החוזה, המגבלות וטיפול בשגיאות.
מה נותנת שכבת API נפרדת ללוגיקת המסחר
שכבת API נפרדת היא לא «שכבה מיותרת לשם היופי», אלא מעגל שמקבל הזמנות, מאמת אותן ומעמיד אותן בתור לפני ליבת המסחר. התעבורה, הפורמטים והמגבלות חיים כאן, והליבה מעבדת רק זרם מנורמל ואינה יודעת מאין הגיע. בידוד כזה של לוגיקת המסחר נותן את הדבר העיקרי: פרץ בכניסה אינו הופך לעלייה בזמן התגובה של ההתאמה.
בפרצים השכבה פועלת כמאגר (buffer) עם מדיניות מפורשת: הגבלת תדירות לפי מפתח גישה, עדיפות לביטולים לפני הזמנות חדשות, אידמפוטנטיות לפי מזהה לקוח, כדי שחזרה על בקשה לא תפתח פוזיציה שנייה. השהיות הזנב נשארות בתחום מוגדר ולא גדלות באופן ליניארי עם העומס. המדד כאן הוא זמן התגובה באחוזונים גבוהים תחת השיא ושיעור ההזמנות שנדחו עם סיבה מפורשת.
זמן השחזור נקבע מכך שהשכבה מנהלת יומן של הזמנות שהתקבלו לפני העברתן לליבה. בעת הפעלה מחדש או תקלה בליבה, הזמנות שאינן מאושרות מופעלות מחדש מהיומן, הלקוח מקבל סטטוס סופי ולא פעולה «תקועה».
בפועל זה הופך את השחזור מבירור ידני לחזרה אוטומטית: שיעור ההזמנות שאבדו שואף לאפס בתוך חלון שמירת היומן.
נעלם סוג הכשל היקר ביותר — «ההזמנה התקבלה, אך לא בוצעה ולא בוטלה», שבו משחזרים את הפוזיציה לפי דפי חשבון. נשארות שגיאות מפורשות עם קוד ותגובה, שהלקוח מטפל בהן בעצמו, בלי לפנות לתמיכה.
בד בבד השכבה מפרידה בין שחרורים: שינויים בלוגיקת המסחר אינם נוגעים בחוזה הגישה, והרחבת פורמטים אינה דורשת עצירה של הליבה.
בקשות לפי דרישה או זרם: השוואת מצבים
ליבת המסחר מוסרת נתונים בשתי דרכים, והבחירה ביניהן קובעת גם את השהיית התגובה וגם את העומס על התשתית. בקשות חד-פעמיות לפי דרישה מחזירות חיתוך של המצב ברגע הקריאה: יתרה, רשימת אורדרים, היסטוריית עסקאות לתקופה. זרם מתמשך מחזיק חיבור פתוח ומשלים שינויים עם היווצרותם — ספר הזמנות, שערים, סטטוסים של אורדרים.
מצב הגישה נבחר לפי פרופיל העומס: כמה לקוחות נמצאים בו-זמנית ברשת, באיזו תדירות משתנים הנתונים והאם פיגור אחרי השוק הוא קריטי. להלן שלוש אפשרויות והמגבלות שלהן.
| מצב גישה | מתי מתאים | במה מוגבל |
|---|---|---|
| בקשות חד-פעמיות לפי דרישה | נתוני עזר, היסטוריית עסקאות ודוחות, פעולות של מפעיל, בדיקת יתרה נדירה | השהיה בכל קריאה, מגבלות תדירות פניות, שינוי מחיר בין קריאות אינו נראה; סקר תכוף מעמיס לחינם על הליבה |
| זרם עדכונים מתמשך | שערים, ספר הזמנות, פיד עסקאות, ווידג'טים למסחר — כל מקום שבו צריך לראות את השוק ללא השהיה | מחזיק חיבור לכל לקוח, דורש התחברות מחדש ושליחת מה שהוחמץ, רגיש לניתוקים ברשתות סלולריות |
| תוכנית היברידית | אפליקציית פרודקשן של הבורסה: זרם לנתוני שוק, בקשות חד-פעמיות להיסטוריה ולפעולות פרטיות | מורכבת יותר בפיתוח ובתחזוקה: שני סטים של הרשאות גישה, סנכרון מצב לאחר ניתוק, בקרת עומס נפרדת |
התוכנית ההיברידית נפוצה ביותר בפרודקשן: היא מפחיתה את נפח התעבורה ומפשטת את השחזור לאחר ניתוק החיבור.
כיצד מתבצעת ההטמעה: שלבי העבודה ההנדסית
אנו עובדים לפי רצף שבו כל שלב מסתיים בחפץ (artifact) שניתן לבדוק, ולא בדוח ביניים. הסדר עקרוני: שינויים במעגל המסחר נעים מקריאה לכתיבה, ולכן תחילה מתעדים כיצד המערכת חיה כעת, ורק אחר כך נוגעים במה שההזמנות עוברות דרכו.
-
ביקורת המעגל. מפרקים שירותים, תורים, מאגרי נתונים ומגבלות קיימות בצד ספקי הנזילות. מאתרים היכן אובדים אירועים, באילו בקשות גדלה ההשהיה ואילו מתודות כבר משתמשים בהן הלקוחות. התוצאה — מפת צווארי בקבוק עם עדיפויות.
-
תרשים האינטראקציה. מתכננים חוזים: מתודות REST לבקשות ומינויים WebSocket לזרמי מחירים, ספר הזמנות ועסקאות. מתעדים פורמטי תגובות, קודי שגיאה, מגבלות תדירות והתנהגות בעת ניתוק חיבור, כדי שהלקוח והצוות שלכם יקראו מסמך אחד.
-
תוכנית נסיגה. מתודות חדשות מוסיפים לצד הקודמות, נקודות המיתוג נשארות בשליטה, וגרסת הממשק חיה במקביל עד מעבר הלקוחות. נסיגה היא החזרת התעבורה למעגל הישן בלי לאבד הזמנות.
-
בדיקה תחת עומס. מריצים פרופיל הקרוב לפרודקשן: שיאי אורדרים, מינויים המוניים, התחברויות מחדש. מסתכלים לא רק על תפוקה, אלא גם על התנהגות בכשלים חלקיים — מה רואה הלקוח כאשר צומת אחד נופל.
-
נראות. מדדים לכל מתודה, יומני בקשות, התראות על סטיות מהנורמה. לפני התפעול צריך להיות גלוי איזה לקוח ואיזו קריאה יוצרים צניחה.
-
העברת נהלים. מוסרים תיעוד של חוזים, תרשימים, מדיניות תדירות ונהלים לאירועים, ומקיימים בירור עם המהנדסים שלכם. בהמשך התמיכה באחריותכם או נשארת אצלנו.
מה אנו מעבירים ללקוח: קונפיגורציות ונהלים
אנו מעבירים לא תיקייה עם תיאור, אלא ערכה עובדת: הקונפיגורציות נמצאות במאגר הקוד לצד הקוד, נפרסות על סביבה נקייה בלעדינו, ותרשימים ומדיניות מנוהלים בגרסאות יחד עם השינויים. להלן מה בדיוק עובר ללקוח בסיום הפרויקט.
- קונפיגורציות שירותים — פרמטרים לחיבור לזרמי שערים, מגבלות תדירות בקשות, פרופילי עומס, משתני סביבה וסדר רוטציית מפתחות.
- תרשימי זרמי נתונים — המסלול ממקור המחירים ועד רישום העסקה: היכן נמצא המטמון, היכן תור האירועים, ואילו ערוצי WebSocket וקבוצות מתודות REST עוברים לצידו.
- מדיניות גישה ומגבלות — מטריצת תפקידים, מפתחות נפרדים לקריאה ולפעולות מסחר, מגבלות לפי סכומים ותדירות, כללי חסימה בעת אנומליות.
- נוהל תפעול — חלונות תחזוקה, סדר הפצת שינויים, ניטור עם ספי התראה ופעולות התורן בסטיות אופייניות.
- תרחישי שחזור — נקודות נסיגה, סדר עלייה מגיבויים, סנכרון מחדש של ספר ההזמנות והיתרות, בדיקת שלמות לאחר השחזור.
- תוצאות בדיקות — פרופיל העומס שתחתיו נבדק, דוח השהיות וכשלים, רשימת מגבלות ידועות עם הערכת סיכון.
הערכה חיה יחד עם הקוד: בשינוי תרשים או מדיניות המסמך מתוקן באותו שינוי, אחרת הוא מתיישן בתוך שבוע ומשמרת התורנים שוב פונה להתכתבות.
מקרה בוחן: הבורסה גדלה פי חמישה בלי לשכתב את הליבה
הבורסה הגיעה אלינו בשלב שבו ליבת המסחר החזיקה את העומס, אך שכבת ה-API כבר לא. בשלושת אלפים חיבורים בו-זמנית ב-WebSocket, תור הפרסום של נתוני השוק גדל מהר יותר משהספיקו לעבד אותו, הזמנות נפלו בגלל timeout, ומשמרת התורנים בילתה חצי מזמנה בבירור ידני של תקלות.
מה הראו המדדים לפני
- 3,000 חיבורים בו-זמנית — התקרה שמעליה החלו הכשלים.
- 92% מההזמנות הגיעו לליבה בשליחה הראשונה, והשאר — חזרות ובדיקה ידנית.
- שחזור לאחר כשל של צומת — כ-40 דקות עבודה של התורן.
- 60–70 בירורים ידניים בשבוע, בעיקר ניתוקי מינויים בתנודות השוק.
מה שינינו ומה התקבל
שכבת ה-API חולקה לשירותים הניתנים להרחבה בלתי תלויה: קליטת הזמנות, מינויים פרטיים של משתמשים ופרסום פומבי של נתוני שוק.
מצב המינויים הועבר למטמון מבוזר על Redis, נוספה שליחה חוזרת עם הגנה מפני כפילויות, הגבלת תדירות בקשות בכניסה והוצאה אוטומטית של צומת מאיזון העומס בעת כישלון בבדיקת חיים.
כתוצאה מכך מספר החיבורים בו-זמנית גדל ל-15,000, שיעור ההזמנות המוצלחות — ל-99.7%, ושחזור צומת אורך פחות משתי דקות בלי מעורבות התורן. הבירורים הידניים הצטמצמו ל-1–2 בשבוע והם נוגעים למצבי שוק שנויים במחלוקת, ולא לכשלי תשתית. את ליבת המסחר לא שינינו — הגידול פי חמישה עבר על הלוגיקה הקיימת.
מה עושים אם ליבת המסחר כבר פועלת?
ליבה פעילה היא נכס שאי אפשר לעצור לשם תיקון. לכן את שכבת הגישה אנו בונים לצידה, ולא בתוכה: הליבה ממשיכה לחשב אורדרים, פוזיציות וסיכונים, ורק האופן שבו הנתונים האלה יוצאים החוצה משתנה. גישה כזו מסירה את הסיכון העיקרי של הפרויקט — את הצורך לשכתב את מה שכבר מניב מחזור.
מבחוץ מופיע שער גישה: הוא מחזיק חוזים לאפליקציות לקוח ומתרגם אותם לממשקים הפנימיים של הליבה דרך מתאמים. הליבה אינה נכתבת מחדש — המתאם קורא את אותם טבלאות ותורים כמו קודם, ומתרגם אותם לבקשות סינכרוניות ולמינויים זורמים לאירועים.
את החוזה מתעדים ב-OpenAPI, כדי שצוותי הלקוח, אפליקציות המובייל והאינטגרטורים החיצוניים יעבדו עם מסמך אחד, ולא עם הסכמות שבעל פה.
חיבור מדורג נותן סיכון מבוקר: תחילה השער מוסר רק נתוני שוק, אחר כך היסטוריית עסקאות ויתרות, ורק לבסוף פעולות המשפיעות על מצב החשבון. כל שלב עובר תחת השוואה — בקשות זהות יוצאות למסלול הישן ולמסלול החדש, ופערים בתגובות נרשמים ביומן ומבוררים לפני המיתוג. חלק התעבורה במסלול החדש גדל במדרגות, ולא במיתוג אחד.
תאימות הממשקים נשמרת ברמת החוזה: גרסאות קודמות של שדות אינן נמחקות כל עוד מדדי הקריאות מראים לקוחות פעילים, והתיישנות מוכרזת לפי שימוש בפועל ולא לפי לוח שנה. נסיגה לאחור היא תנאי הכרחי בקבלה: הניתוב חוזר למסלול הקודם בפעולה אחת, בלי מיגרציות ובלי אובדן מצב. מקור האמת נשאר בליבה, ולכן המסלול הישן והחדש אינם מתפצלים בנתונים.
כך הבורסה ממשיכה לסחור בלי עצירה, ושכבת הגישה נבנית חלקים-חלקים ובכל רגע יכולה להיות מוחזרת לאחור. תארו את המשימה שלכם — נחזור עם הערכה ותוכנית לפי שלבים.
ספקות טכניים שכדאי להסיר לפני ההתחלה
הספקות של לקוחות נשמעים אותו דבר, והתשובות עליהם קובעות אם הבורסה תעמוד בעומס או תתפרק בפרץ הפעילות הראשון. נבחן את השאלות ההנדסיות המרכזיות לפני תחילת העבודה — כדי שהחלטות ארכיטקטוניות יידונו בשלב התוכנית, ולא ברגע התקלה.
כיצד מובטחת שלמות הנתונים בעת הכתיבה?
כל פעולה מתבצעת בטרנזקציה יחד עם רישום ביומן: יתרות, אורדרים ועסקאות משתנים בפעולה אטומית אחת ואינם יכולים להתפצל בעת ניתוק. שליחה חוזרת של בקשה נחסמת לפי מפתח אידמפוטנטי — כפילות אינה הופכת לעסקה שנייה.
כיצד מתעדכנת המערכת בלי לנתק את החיבורים של הלקוח?
השירותים מתעדכנים בזה אחר זה: הגרסה החדשה עולה לצד הישנה, מקבלת תעבורה, ורק אחר כך מוצאת הישנה משימוש. מינויים פעילים עוברים אליה בהעברה חלקה, בלי אובדן עדכונים ובלי פרץ התחברויות מחדש, והממשק הקודם נשאר תואם למשך המעבר.
כיצד מופרדות הרשאות הגישה?
הגישה נבנית על תפקידים ומפתחות עם הרשאות נפרדות: קריאה, מסחר ומשיכה — זכויות שונות, בתוספת מגבלות לפי נפח ורשימת כתובות. מפתח עם הרשאת מסחר אינו מאפשר למשוך יתרה, והרוטציה והשלילה של הגישה מתרחשות בלי לעצור את השירות.
מה קורה בעת אי-התאמה עם מערכת חיצונית?
את אי-ההתאמה תופסת התאמה תקופתית, וכל מקרה נכנס לתור בירור עם הקשר מלא: יומן הפעולות, תגובות המערכות החיצוניות, מצב האורדר ברגע התקלה. היומן מנוהל בצורה בלתי ניתנת לשינוי, ולכן שחזור הפוזיציה של הלקוח נשען על המקור הראשוני ולא על השערה.
נדון במשימה: מה נדרש כדי להתחיל בעבודה
כדי להעריך פיתוח API של בורסת קריפטו, ולא להשיב בטווח של «בערך כל כך», נדרש סט מינימלי של נתוני קלט. ככל שהקלט konkרטי יותר, כך לוחות הזמנים של השלבים מדויקים יותר והפחות עיבודים מחדש במפגש עם ליבת המסחר.
- אילו תרחישים משרת הממשק: פעולות מסחר, זרם שערים ועסקאות בזמן אמת, היסטוריה, משיכת כספים, קריאות תפעוליות.
- מה כבר קיים בצד הליבה: כיצד היא מוסרת מצב כעת, אילו נתונים זמינים ישירות ואילו יהיה צורך להרכיב.
- מודל הגישה: כיצד מונפקים מפתחות, האם נדרשות הרשאות לפי תפקידים ומגבלות על תדירות הפניות.
- דרישות לעומס ולאמינות: תדירות בקשות שיא, השהיית תגובה מותרת, התנהגות בעת ניתוק חיבור.
- תשתית: היכן מתארחים השירותים, האם קיימים תיעוד ביומן וניטור, כיצד מופצים עדכונים.
- לוחות הזמנים שלכם והנקודות שעד אליהן הממשק צריך להיות מוכן — לפיהן נבנה את סדר השלבים.
סדר הדיון פשוט: בירור קצר של המשימה, אחר כך שאלות הבהרה לפי הרשימה לעיל, ונעבור בנפרד על אילו קריאות הן סינכרוניות ואילו זורמות כזרם אירועים. לאחר מכן נשלח תוכנית עבודה כתובה: תכנון תרשיםים וכללי גישה, מימוש, בדיקות על מעגל בדיקה, הרצות עומס, תיעוד והעלאה לתפעול.
התכנון אורך בדרך כלל שבוע-שבועיים, המימוש — משלושה שבועות ואילך, והבדיקות והתיעוד מתקדמים במקביל אליו. ההערכה והתוכנית נשארות אצלכם ללא תלות בהחלטה להתחיל.







