पब्लिश के ठीक बाद क्रैश होने वाले ऐप्स को पकड़ना
25 सितंबर को तीन पब्लिश सफल मार्क हो गए, जबकि ऐप की API हर बूट के कुछ सेकंड में क्रैश हो रही थी। क्योंकि वे "सफल" हुए थे, कोई रोलबैक नहीं चला; कुछ मिनट बाद एक बैकग्राउंड जाँच ने उन्हें विफल घोषित किया, और पूरी साइट 404 पर चली गई। हेल्थ चेक होस्टिंग प्लेटफ़ॉर्म की इवेंट सूची में क्रैश गिन रहा था, जो हर मशीन के लिए केवल आखिरी पाँच इवेंट रखती है, इसलिए क्रैश लूप उसे भरा रखता है और गिनती कभी नहीं बढ़ती। अब वह इसके बजाय सबसे नए क्रैश का समय तुलना करता है, और क्रैश-लूप करने वाला पब्लिश विफल होता है और पिछला वर्शन वापस लाता है।
पब्लिश किस चीज़ का इंतज़ार करता है
जब आप Mythex पर बैकएंड वाला ऐप पब्लिश करते हैं, तो नया वर्शन हमारे होस्टिंग प्लेटफ़ॉर्म की मशीनों पर रोल आउट होता है, और एक हेल्थ चेक तय करता है कि पब्लिश लाइव हुआ या विफल। अगर विफल हुआ, तो रोलबैक पिछला वर्शन वापस लगा देता है।
मुश्किल बात यह है कि "शुरू हुआ" और "सेवा दे रहा है" एक चीज़ नहीं हैं। प्लेटफ़ॉर्म एक मशीन को तब शुरू हुआ बताता है जब वह ऊपर आती है। जो ऐप बूट के एक सेकंड बाद क्रैश होता है, वह तुरंत रीस्टार्ट होता है, और थोड़ी देर बाद फिर शुरू हुआ पढ़ा जाता है। इसलिए हेल्थ चेक समय के साथ कुछ परतों वाला बन गया था:
- दो बार देखें। मशीन के शुरू हुआ पढ़े जाने के बाद थोड़ी देर रुकें और फिर से देखें। बूट पर क्रैश अक्सर दूसरी जाँच में पकड़ में आता है।
- क्रैश लूप पर नज़र रखें। अगर प्लेटफ़ॉर्म बताता है कि कोई मशीन बार-बार क्रैश हुई और उसने उसे रीस्टार्ट करना छोड़ दिया, तो विफल करें।
- पब्लिश शुरू होने के बाद के क्रैश गिनें। दो "शुरू हुआ" जाँचें रीस्टार्ट के बीच में पड़ सकती हैं। इसलिए अगर इस पब्लिश के शुरू होने के बाद कोई भी क्रैश हुआ है, तो तीसरी बार देखें; अगर पिछली जाँच से ज़्यादा क्रैश हैं, तो ऐप टिक नहीं रहा।
यहाँ जो जाँच विफल हुई, वह तीसरी थी।
गिनती स्थिर क्यों रही
क्रैश की जानकारी हर मशीन की इवेंट सूची से आती है: शुरू होना, बाहर निकलना, रीस्टार्ट। प्लेटफ़ॉर्म हर मशीन के लिए केवल आखिरी पाँच इवेंट रखता है।
एक ऐसे ऐप की कल्पना करें जो हर बूट के 2.5 सेकंड पर क्रैश होता है, जैसा उनमें से एक करता था। हर चक्र में एक क्रैश और एक शुरू होना जुड़ता है। कुछ चक्रों के बाद सूची भर जाती है। उसके बाद हर नया इवेंट एक पुराने को धकेल कर बाहर कर देता है। सूची आगे खिसकती है, लेकिन हमेशा लगभग एक ही मिश्रण रखती है: कुछ क्रैश, कुछ शुरू होने वाले।
इसलिए "पब्लिश शुरू होने के बाद कितने क्रैश हुए" हर बार एक ही संख्या लौटाता था। दूसरी जाँच में, मान लीजिए, दो क्रैश दिखे। तीसरी जाँच में भी दो दिखे, भले ही वे अलग क्रैश थे, लेकिन संख्या वही थी। जाँच ने निष्कर्ष निकाला कि क्रैश होना बंद हो गया है, और पब्लिश पास कर दिया।
25 सितंबर को यह दो ऐप्स पर तीन बार हुआ। हर बार:
- पब्लिश लाइव मार्क हो गया,
- कोई रोलबैक नहीं चला, क्योंकि कुछ विफल नहीं हुआ था,
- हमारा reconciler, एक बैकग्राउंड जॉब जो बाद में डिप्लॉयमेंट जाँचता है, कुछ मिनट बाद डिप्लॉयमेंट को विफल घोषित कर बैठा,
- और पूरी साइट 404 लौटाने लगी।
समय पर विफल होने वाला पब्लिश वसूली योग्य है: रोलबैक पिछला वर्शन वापस लाता है। लेकिन जो पब्लिश कुछ मिनट देर से विफल होता है, सफल घोषित होने के बाद, वह अपना रोलबैक पहले ही छोड़ चुका होता है।
हमने इसे कैसे पकड़ा
हमने इसे लोकल पर दोहराया: एक काम करती API ली, उसे सोने दिया, फिर एक ऐसे बदलाव के साथ रीपब्लिश किया जो बूट पर क्रैश होता था। हेल्थ चेक ने उसे लाइव मार्क कर दिया।
यह प्रोडक्शन से मेल खाता था: तीनों पब्लिश में ऐप हर बूट पर कुछ सेकंड में मर रहा था, फिर भी जिस क्रैश गिनती की जाँच तुलना कर रही थी, वह जाँचों के बीच कभी नहीं बढ़ी।
समाधान: गिनती नहीं, सबसे नए क्रैश की तुलना
क्रैश गिनने के बजाय, अब जाँच पब्लिश शुरू होने के बाद सबसे हाल के क्रैश का समय देखती है।
अगर दूसरी जाँच में पब्लिश शुरू होने के बाद कोई भी क्रैश दिखता है, तो जाँच रुककर तीसरी बार देखती है। अगर तीसरी जाँच में सबसे नया क्रैश दूसरी जाँच के सबसे नए क्रैश से बाद का है, तो मशीन बीच में फिर क्रैश हुई। वह टिक नहीं रही, और पब्लिश इस संदेश के साथ विफल होता है कि पब्लिश के बाद से मशीन बार-बार क्रैश हो रही है और अब भी रीस्टार्ट हो रही है।
यह तब भी काम करता है जब इवेंट सूची कितनी भी छोटी हो। पाँच इवेंट की खिसकती खिड़की यह छिपा सकती है कि कितने क्रैश हुए, लेकिन यह नहीं छिपा सकती कि अभी एक नया क्रैश हुआ है; सबसे नया इवेंट हमेशा रहता है।
इस बदलाव के साथ लोकल दोहराव सही व्यवहार करता है: पब्लिश विफल होता है, और पिछली इमेज वापस आ जाती है। एक टेस्ट भी है जो प्लेटफ़ॉर्म के व्यवहार की नकल करता है, जहाँ हर जाँच एक क्रैश और एक शुरू होना जोड़ती है और सूची को पाँच तक काटती है, और जाँचता है कि नतीजा पास नहीं बल्कि विफलता है।
हमने इससे क्या सीखा
- जिस डेटा की गिनती कर रहे हैं उसका आकार जानें। सीमित सूची पर गिनती भरी हुई सूची के बाद कुछ मतलब नहीं रखती। सीमा छिपी नहीं थी; बस हमने जाँच को उसके हिसाब से डिज़ाइन नहीं किया था।
- "कितने हुए?" की जगह "कुछ नया हुआ क्या?" को तरजीह दें। सबसे नया टाइमस्टैम्प काट-छाँट के बाद भी बचा रहता है। कुल योग नहीं बचता।
- देर से विफलता, जल्दी विफलता से बुरी है। वही टूटा हुआ बिल्ड कोई नुकसान नहीं करता अगर पब्लिश विफल होकर रोलबैक करे, और साइट बंद कर देता है अगर पहले उसे सफल घोषित कर दिया गया हो।
- असली परिस्थितियों में दोहराएँ। इस बग के लिए ऐसी मशीन चाहिए थी जो अपनी इवेंट सूची भरने जितनी बार पहले ही क्रैश हो चुकी हो। टेस्ट में एक ही त्वरित क्रैश इसे नहीं दिखाता।
यह सुधार उसी दिन के एक और सुधार के साथ जुड़ता है, जिसने यह पक्का किया कि रोलबैक पुराना वर्शन वापस लाए, न कि उसे मिटाए: विफल रीपब्लिश कभी चालू बैकएंड को नहीं मिटाता। अगर आपका अपना ऐप शुरू होते समय क्रैश होने के कारण पब्लिश नहीं होता, तो पब्लिश समस्या-निवारण डॉक्स और हमारी AI से बने ऐप को डीबग करने गाइड से शुरू करना अच्छा रहेगा।