פיתוח הבקנד של dApp: היכן נשברת הסנכרון עם הרשת
הבקנד של dApp עומד בין הממשק לרשת המבוזרת, וזה המקום השביר ביותר במערכת. תגובת הצומת מגיעה באיחור או לא מגיעה כלל, והאפליקציה כבר מציגה למשתמש הצלחה. כל עוד זה לא סגור, הלוגיקה מעל השרשרת נשענת על מצב שעדיין אינו קיים ברשת.
סוג נפרד של כשלים — עסקאות תקועות. החתימה נשלחה לרשת, העמלה הייתה נמוכה מהמחיר השוקי הנוכחי, והפעולה תלויה שעות, וחוסמת את התור של הבאות. בלי מעקב אחר סטטוס ושליחה חוזרת עם עדכון פרמטרים, המשתמש לא מבין אם חויב במשהו, והתמיכה לא יכולה לתת תשובה ודאית.
כפילויות של פעולות מופיעות במקום שבו מטפל ההתראות מופעל מחדש באמצע העבודה או שהרשת מספקת אירוע אחד שוב. אותה עסקה נספרת פעמיים, היתרות והמגבלות סוטות מהמצב בפועל של השרשרת. אידמפוטנטיות לפי ההאש של העסקה ומאגר נפרד לאירועים שעובדו מסירים את סוג השגיאות הזה לחלוטין.
פער בין הממשק לשרשרת מוסיף גם reorg: הבלוק שעליו נשען החישוב נופל מהענף הראשי. זה לא מתוקן בקוסמטיקה, אלא בנקודת קריאה אחודה עם עומק אישורים קבוע ומצבי פעולה מפורשים. אנחנו בונים שירותים כאלה עם web3.py — פיתוח הבקנד של dApp כאן מתחיל ממודל הכשלים, ולא מהמסכים.
להלן נפרט כיצד נסגרים הסנכרון עם הרשת, אי-זמינות הצומת וכפילויות הפעולות.
מה נותן בקנד ייעודי: מהירות תגובה ועמידות
בקנד ייעודי לאפליקציה מבוזרת נדרש כדי שהממשק יגיב לפעולות המשתמש מבלי להמתין לאישור הסופי ברשת. בקשות לקריאת מצב ולהכנת פעולות מטופלות מהאינדקס שלנו ומהמטמון המקומי, ולכן זמן התגובה נמדד בשברירי שנייה, ולא בשניות של המתנה. הרשת נשארת מקור האמת, אך מפסיקה להיות הנקודה שכל לחיצה נתקעת בה.
עמידות השירות נשענת על אידמפוטנטיות: לכל פעולה יש מפתח משלה, ולכן שליחות חוזרות בעת ניתוק הקשר לא יוצרות כפילויות — הפעולה או עוברת פעם אחת, או מחזירה תוצאה שכבר ידועה.
זה סוגר סוג של כשלים שהיקר ביותר לתפעול: חיובים כפולים, מצב שאבד בין בקשות, פעולות "תקועות" בלי סטטוס ברור.
טיפול בעומסי שיא הועבר לתור עם הגבלת קצב ועדיפויות. בעת זינוק בפעילות השירות לא קורס ולא מאבד משימות: הוא פורש את העיבוד לאורך זמן, והממשק מציג את מצב הפעולה האמיתי במקום "הושלם" כוזב. פעולות לא מאושרות חוזרות בהשהיה גדלה והולכת עם תקרה — זה מכבה סערת בקשות בפעולות המוניות.
התוצאה המעשית: שיעור התרחישים שעוברים ללא התערבות ידנית גבוה מתשעים אחוזים. המפעיל מטפל במקרים לא טיפוסיים, ולא בכל כשל רשת.
קריאות סינכרוניות, תורי משימות ועיבוד זורם: השוואה
קריאה סינכרונית ישירה לצומת — הנתיב הפשוט ביותר: התגובה מגיעה באותה בקשה, אין צורך בתשתית נפרדת. המגבלה היא שהתגובה תלויה כולה בשירות חיצוני, וניתוק החיבור מיד לאחר שליחת העסקה מותיר אי-ודאות — האם לספור את הפעולה כבוצעה או לחזור עליה.
עיבוד רקע דרך תור משימות מפריד בין קבלת הבקשה לעבודה עם הרשת: הלקוח מקבל מזהה פעולה ושולף את המצב בסקר. עיבוד זורם של אירועים נותן תמונה הפוכה — השירות קורא את יומן הבלוקים ויוזם תגובה בעצמו. בפועל לרוב מנצחת שיטה היברידית: הכתיבה עוברת דרך תור, והמצב נאסף בזרם אירועים.
| שיטה | מתי מתאימה | מגבלות |
|---|---|---|
| קריאות סינכרוניות | פעולות נדירות, קריאת מצב, פעולות ידניות של מנהל | התגובה תלויה בשירות חיצוני, אין חזרות בעת ניתוק, בשיא הבקשות גדלות במטפלים |
| תור משימות | עסקאות שלא ניתן לבצע ברגע הבקשה: תשלומים, מינט, פעולות מרוכזות | השהיה בין הבקשה לתוצאה, יש צורך במפתח אידמפוטנטיות, אחרת חזרה תיצור פעולה שנייה |
| עיבוד זורם | חשבונאות רציפה: יתרות, היסטוריה, התראות, אינדוקסציה | חזרה מורכבת בעת בנייה מחדש של השרשרת, יש לשמור נקודת קריאה ולהדביק את החסר |
| שיטה היברידית | שירות ייצור, שבו קריאה וכתיבה חיים לפי כללים שונים | יותר קוד ונקודות כשל, נדרש הפרדה מפורשת של אחריות בין קו הבקשה לעובדים |
ההבדל מתגלה בכשלים, ולא במצב רגוע. לכן את השיטה בוחרים לפי עומס, דרישות לזמן תגובה ועד כמה חזרה על פעולה היא קריטית — ותור, זרם וחיבור ישיר בשירות אחד מופרדים לנתיבים שונים.
שלבי העבודה: אודיט, תכנון, הגדרה, בדיקה, מסירה
העבודה מחולקת לשלבים כך שכל אחד מסתיים בארטיפקט שניתן לבדוק: מפת אינטגרציה, תרשים, קונפיגורציה או דוח עומס. מצב הפרויקט נראה בכל שלב — פערים מהציפיות מתבררים לפני שהשינויים עוברים לענף הראשי.
-
אודיט האינטגרציה. אנחנו מצלמים את המצב הנוכחי: אילו צמתים קוראים את הרשת, כיצד נוצרות וחתומות העסקאות, היכן נשמרים המפתחות, כיצד מטופלים ארגונים מחדש של בלוקים ושליחות חוזרות של אירועים. בפלט — רשימת צווארי בקבוק עם הערכת סיכון ורשימת מה שנעשה בו שימוש חוזר.
-
תרשים השירותים. מפרקים את הבקנד לשכבות: קבלת בקשות, עיבוד אירועים, תור משימות, מאגר המצב. קובעים היכן נדרשת אידמפוטנטיות, כיצד מופרדים קריאה וכתיבה, לפי אילו מפתחות נבנית הסרת הכפילויות.
-
הגדרת התורים. מפזרים משימות לפי עדיפויות ותורים נפרדים: אישור עסקאות, אינדוקסציה, חזרות מושהות. קובעים מגבלות מקביליות ומדיניות חזרות, כדי שמשימה תקועה לא תחסום את האחרות, והודעות "מורעלות" יישלחו לבדיקה בנפרד.
-
הרכבות API וקונפיגורציה. מתארים חוזים, ולידציה של נתוני קלט, מפתחות אידמפוטנטיות ומגבלות קצב בקשות. סודות ופרמטרים של סביבות מוצאים מהקוד.
-
בדיקה בעומס. מריצים הקלטה של אירועים אמיתיים וזרם סינתטי, מודדים השהיה מהופעת הבלוק עד לתגובת השירות, בודקים התנהגות בעת כשל צומת והצפת תור.
-
מסירת הפרויקט. מוסרים את המאגר, המיגרציות, תרשים הפריסה, מדדים עם התראות וסדר הפעולות במקרה של תקרית. עורכים סקירה עם צוות הלקוח, כדי שהפיתוח העתידי ימשיך באופן עצמאי.
מה נשאר אצלכם: תרשימים, קונפיגורציות ותקנונים
מסירת פרויקט בלי ארטיפקטים הופכת אותו במהירות לקופסה שחורה: הצוות עזב, ואין מי שיבין למה העובד לא מדביק את הרשת או כיצד לסובב מפתח חתימה. לכן המסירה היא שלב עבודה נפרד, ולא ארכיון בסוף. הנה מה שנשאר אצלכם במאגר ובבסיס הידע הפנימי.
- קונפיגורציות סביבות — קובצי משתנים לסביבת פיתוח מקומית, לבדיקות ולסביבת עבודה; הסודות מופרדים בנפרד, לכל קובץ יש דוגמת מילוי. עותק של השירות עולה בלי התכתבות עם המחברים.
- תרשימי ארכיטקטורה — כיצד קשורים הצמתים, התורים ועובדי העיבוד; בנפרד מסומנת ההתנהגות בעת נפילת רכיב ולאן הולכת הניסיון החוזר.
- מדיניות הרשאות — תפקידים והרשאות, הפרדה בין מפתחות חתימה למפתחות לקריאה בלבד, כללי שמירת סודות וסדר סיבובם.
- תקנון עדכונים — כיצד יוצאת גרסה חדשה: בנייה, הרצת בדיקות, פריסה, חלון חזרה ומי מקבל את ההחלטה לעצור את השחרור.
- תיעוד API — שיטות, תרשימי בקשות ותגובות, קודי שגיאה, מגבלות ודוגמאות קריאה לאפליקציית הלקוח שלכם או לשירות חיצוני.
- הוראות תפעול — הפעלה והפעלה מחדש של עובדים, קריאת לוגים, פעולות בעת חוסר סנכרון מצב עם הרשת, כשלים טיפוסיים עם פתרונות מוכנים.
- מוניטורינג מוגדר — התראות על השהיית עיבוד, שגיאות כתיבה ומחסור במשאבים בחשבון השירות, עם ספי הפעלה ונמען.
לפני המסירה אנחנו מקימים את הסביבה מאפס לפי אותם מסמכים על מכונה נקייה: אם שלב לא משוחזר, ההוראה חוזרת לתיקון.
מקרה בוחן: כיצד הסרנו השבתות בעומס שיא
הלקוח — שירות בקשות על הבלוקצ'יין: המשתמש חותם על פעולה, הבקנד שולח את העסקה ועוקב אחרי הכללתה בבלוק. קבלת בקשות, תור משימות והשליחה הוחזקו בתהליך Python אחד עם web3.py: בזרם של 3–5 אלף סשנים במקביל הצומת הגיב באיחור, התור התנפח, וחלק מהעסקאות החתומות לא הגיעו לבלוק.
מה היה
שיעור הפעולות האבודות — 4–6% בשעת שיא: שליחות שפג תוקפן ו-nonce שנדרסו שקעו בתור ופשוט הושלכו. השחזור לאחר נפילת צומת — 40–60 דקות של עבודה ידנית: להעלות את השירות, להשוות מצב ארנקים, להשלים שליחות תקועות. הממשק בזמן הזה החזיר timeout, והמשתמשים לחצו "שלח" שוב, ויצרו כפילויות.
מה שינינו ומה נהיה
את התור הוצאנו לשכבה נפרדת עם הגבלת אורך ועדיפויות, את השליחה עשינו אידמפוטנטית לפי מפתח הבקשה, והוספנו חשבונאות nonce משלנו עם חישוב מחדש של החתימה בעת חזרה. חיברנו צמתים עם החלפה אוטומטית, ומצב כל עסקה נשמר עד לאישור סופי — אתחול השירות לא מאבד יותר דבר.
שיעור הפעולות האבודות ירד ל-0.1%, ואלו רק כאלה שנדחו על ידי הרשת עם סיבה מפורשת. השחזור לאחר כשל צומת — 90 שניות וללא מעורבות מהנדס: התעבורה עוברת לגיבוי, ושליחות תקועות מושלמות מהמאגר. בשעת שיא הממשק עומד בעומס המחושב, כפילויות נחתכות בכניסה, והתור והאישורים נראים בגרפים.
במה שונה צומת רשת משלכם מספק חיצוני
ספק חיצוני הוא שער לרשת במנוי: הקריאות עוברות דרך מאגר משותף, ולא דרך התשתית שלכם. ההתחלה אורכת שעות, אך התנהגות השירות תלויה במתכנן זר — בשיא מגיע סירוב 429 וחזרות במקום בלוק טרי. מגבלות הבקשות נספרות לפי שיטה ושנייה, ולכן שליפות כבדות על טווח בלוקים גדול נחתכות ראשונות.
צומת רשת משלכם מסיר את מגבלות הבקשות לחלוטין: את רוחב הפס מגביל רק החומרה, ואתם מחליטים כמה מנויים מקבילים לאירועים להחזיק. זה קריטי כאשר שירות אינדוקסציה קורא לוגים ברציפות, ומשימות רקע מדביקות במקביל בלוקים שפשלו.
מכאן מתחיל העומס על התשתית. צומת מלא דורש דיסק מהיר וסנכרון יציב, צומת ארכיוני שומר מצבים של כל הבלוקים וגדל באופן לינארי. מנגד, חישוב מחדש של ההיסטוריה לאחר כשל, השוואת יתרות וייצוא לתקופה שרירותית הופכים לשגרה, ולא לפרויקט נפרד.
בפועל רוב השירותים פועלים במצב היברידי: צומת משלנו סוגר את הנתיב החם — שליחת עסקאות וקריאת בלוקים טריים, ו-Infura נשאר גיבוי בזמן עדכון הלקוח או פיגור. בקוד זה הופך לתור קריאות, איחוד בקשות לאצוות, מטמון כותרות ובדיקת מצב ברקע, שמחליפה מקור בעת פיגור.
שאלות טכניות: צמתים, מגבלות, שליחות חוזרות
בקנד אסינכרוני של אפליקציה מבוזרת לא חי בוואקום: צמתים ציבוריים מגיבים באיחור, מחזירים שגיאה בעת חריגה ממגבלת הבקשות ולפעמים מאבדים קשר לעשרות שניות.
אנחנו מציבים לפני השירות מאגר ספקים עם החלפה אוטומטית בעת כשלים, וכל שליחה לרשת מקבלת מזהה משלה — הפעלה חוזרת של המטפל לא יוצרת עסקה שנייה. מגבלות הבקשות הופכות לפרמטר קונפיגורציה צפוי, ולא למקור כשלים בשעת שיא.
גם פעולות לא גמורות לא הולכות לאיבוד. היומן שומר את מצב כל משימה, ולאחר אתחול השירות הוא טוען את מה שנשאר בסטטוס "נשלח, אין אישור", ומשווה את התוצאה לפי ההאש. המשתמש רואה לא "תקוע", אלא את סטטוס הפעולה העדכני.
מה יקרה אם צומת הספק יתחיל להשיב בשגיאות?
השירות עובר לצומת גיבוי מהמאגר, והמשימה חוזרת לתור עם השהיה מוגדלת בין ניסיונות. אם כולם לא זמינים — הפעולות מצטברות ביומן ומסתיימות לאחר שיקום הקשר, ללא התערבות ידנית.
כיצד נשמרים מפתחות החתימה?
מפתחות פרטיים לא מגיעים לא לקוד ולא ללוגים: הם נשמרים במאגר מבודד, והשירות מבקש חתימה דרך ממשק צר עם סט פעולות מוגבל. הגישה מופרדת לפי תפקידים, כל פנייה נרשמת בלוג ביקורת.
את המוניטורינג מגדירים לפני ההרצה: עומק התור, שיעור השליחות הכושלות, השהיית אישור, התראות על דגרדציה. עדכון תלויות נעשה בתקנון נפרד — תחילה הרצה על רשת בדיקות, אחר כך פריסה, כדי שהחלפת גרסת ספרייה לא תשבור את העבודה עם החוזה.נדון במשימה: נחזור עם הערכה ותוכנית עבודה
כדי שההערכה תישען על עובדות ולא על הנחות, נדרש סט קצר של נתוני פתיחה — בדרך כלל מספיק שיחה אחת וגישה למה שכבר קיים: מאגר, תיאור החוזים, תרשים הסביבות. אנחנו עובדים עם מחסנית Python לבקנד של dApp, ולכן נגיד מיד אילו צמתים ידרשו השלמה ואילו ניתן לעשות בהם שימוש חוזר בלי לשכתב.
מה נדרש מכם להתחלה:
- אילו חוזים כבר פרוסים, באילו רשתות ואילו פעולות הבקנד מבצע בשרשרת.
- מי חותם על העסקאות וכיצד בנויה שמירת המפתחות — מכך תלויה מודל ההרשאות והחזרה לאחור.
- עומס צפוי: כמה פעולות ביום, היכן השיאים, עד כמה קריטית השהיית התגובה.
- סביבות: היכן מפרסים, האם יש רשת בדיקות וכיצד מתבצעת פריסת שחרורים.
- עבודה עם נתונים: האם נדרשת אינדוקסציה של אירועים, היסטוריית פעולות, ייצוא ודוחות.
- מה כבר כתוב: מאגר, תיאור צווארי בקבוק, שגיאות ידועות ומשימות לא סגורות.
- מי מצדכם מתאם את הארכיטקטורה ואת סדרי העדיפויות של השלבים, כדי לא לעכב את העבודה.
בסיכום הדיון במשימה נחזור עם הערכה, תוכנית שלבי יישום והרכב הצוות: מי מוביל את הבקנד, מי אחראי על התשתית, מי סוגר את הבדיקות והקבלה. תארו מה כבר עובד, מה צריך לעבוד ובאילו לוחות זמנים — ונחזור עם תוכנית.







