प्रतिनिधि इंटरव्यू विषय

बैकएंड इंटरव्यू: Node और NGINX टाइमआउट बेमेल होने पर काम पूरा होने के बावजूद एरर क्यों आ सकता है?

बैकएंडमध्यम
Offer.cc संपादकीय टीमप्रकाशित अपडेट किया गया

प्रश्न

एक Node सर्विस NGINX रिवर्स प्रॉक्सी के पीछे स्थित है। एंडपॉइंट कभी-कभी 502 लौटाता है, लेकिन एप्लिकेशन लॉग दिखाते हैं कि जॉब कुछ सेकंड बाद पूरा हो गया। आप टाइमआउट लेयर का पता कैसे लगाएंगे और टाइमआउट बदलने, रिस्पॉन्स स्ट्रीम करने या काम को कतार (queue) में ले जाने के बीच चयन कैसे करेंगे?

प्रॉम्प्ट और दायरा

एक Node एंडपॉइंट कई बाहरी कॉल्स करता है और सामान्यतः 5–35 सेकंड लेता है। Node 60 सेकंड की अनुमति देता है, जबकि NGINX अपना डिफ़ॉल्ट proxy_read_timeout रखता है। प्रोडक्शन उपयोगकर्ताओं को कभी-कभी 502 दिखाई देता है; एप्लिकेशन लॉग बाद में बताता है कि बिज़नेस राइट पूरा हो गया। लोड के तहत, लंबे समय तक चलने वाले कनेक्शन पूल की भी खपत करते हैं।

क्लाइंट, NGINX, Node, डाउनस्ट्रीम डिपेंडेंसी और जॉब स्टोर के लिए एक टाइमलाइन बनाएं। 502 के स्रोत की व्याख्या करें, यह बताएं कि क्लाइंट द्वारा विफलता देखे जाने के बाद भी काम क्यों समाप्त हो सकता है, और सिंक्रोनस रिस्पॉन्स, स्ट्रीमिंग या एसिंक्रोनस कतार का उपयोग कब करना चाहिए। ये संख्याएं इंटरव्यू के अनुमान हैं; मुख्य कौशल क्रॉस-लेयर टाइमआउट सेमेंटिक्स, कैंसिलेशन, साइड-इफेक्ट सीमाएं, आइसोलेशन और फिक्स का प्रमाण हैं, इसलिए यह एक बैकएंड प्रश्न है।

इंटरव्यूअर क्या मूल्यांकन करता है

सक्षम उम्मीदवार हर 502 को पुनः प्रयास (retry) करने के बजाय कनेक्शन क्लोज़, एप्लिकेशन डेडलाइन और बिज़नेस कंप्लीशन को अलग-अलग करते हैं। वे जानते हैं कि NGINX रीड टाइमआउट अपस्ट्रीम रीड्स के बीच के निष्क्रिय समय (idle time) को मापता है, न कि आवश्यक रूप से पूरे रिस्पॉन्स को, और AbortSignal.timeout() केवल उन ऑपरेशनों को सूचित करता है जो वास्तव में सिग्नल को सुनते हैं।

वे प्रॉक्सी, गेटवे, लोड बैलेंसर, SDK और क्लाइंट्स में डिफ़ॉल्ट्स का भी इन्वेंटरी तैयार करते हैं; उपयुक्त होने पर HTTP रिक्वेस्ट्स को लंबे जॉब्स से अलग करते हैं; और यह साबित करते हैं कि सुधार से डुप्लिकेट राइट्स, लीक हुए कनेक्शन या रीट्राय एम्प्लीफिकेशन नहीं होते हैं।

पहले स्पष्ट करने योग्य प्रश्न

  • क्या 502 NGINX द्वारा उत्पन्न किया गया है या Node द्वारा लौटाया गया और फिर से लिखा (rewritten) गया है? हेडर्स, प्रॉक्सी एरर लॉग्स और अपस्ट्रीम एक्सेस लॉग्स की तुलना करें।
  • क्या टाइमआउट होने पर कोई बिज़नेस साइड इफेक्ट कमिट हो चुका था? किसी अज्ञात परिणाम को आँख मूंदकर दोबारा नहीं चलाया जा सकता।
  • क्या इस रिक्वेस्ट में ही परिणाम लौटाना आवश्यक है? यदि केवल अंतिम परिणाम मायने रखता है, तो 35-सेकंड का सिंक्रोनस कनेक्शन अनावश्यक है।
  • क्या अपस्ट्रीम लगातार बाइट्स भेज रहा है? तब रीड-आइडल टाइमआउट और कुल रिक्वेस्ट डेडलाइन के अलग-अलग अर्थ होते हैं।
  • क्या कैंसिलेशन डेटाबेस, HTTP क्लाइंट और बाहरी SDK तक पहुंचता है? ब्राउज़र कनेक्शन बंद करने से हर ऑपरेशन नहीं रुकता।
  • कॉनक्रेन्सी, कनेक्शन-पूल उपयोग, इवेंट-लूप विलंब और कतार की गहराई कैसे बदलती है? संख्याओं को बदलने से पहले बॉटलनेक की पुष्टि करें।

30-सेकंड का उत्तर

“मैं क्लाइंट, NGINX, Node, डाउनस्ट्रीम कॉल्स और स्टोरेज में एक ट्रेस आईडी को कोरिलेट करूँगा ताकि यह पहचाना जा सके कि कौन सी लेयर 502 उत्सर्जित करती है और कब। NGINX proxy_read_timeout रीड्स के बीच निष्क्रिय समय को सीमित करता है; Node की 60-सेकंड की रिक्वेस्ट सेटिंग यह गारंटी नहीं देती है कि क्लाइंट के डिस्कनेक्ट होने के बाद कोई जॉब रुक जाएगी। एक सिंक्रोनस परिणाम के लिए, मैं एक एंड-टू-एंड डेडलाइन परिभाषित करूँगा और प्रॉक्सी, एप्लिकेशन और डाउनस्ट्रीम में क्लीनअप मार्जिन रखूँगा। यदि जॉब इंटरैक्शन बजट से अधिक हो जाती है, तो इसे पर्सिस्ट करें, एक आईडी लौटाएं और एक वर्कर को इसे निष्पादित करने दें। मैं यह सत्यापित करने के लिए विफलताएं इंजेक्ट करूँगा कि कोई डुप्लिकेट साइड इफेक्ट, कनेक्शन की कमी या रीट्राय एम्प्लीफिकेशन न हो।”

चरण-दर-चरण समाधान

टाइमलाइन से शुरुआत करें। क्लाइंट एक रिक्वेस्ट भेजता है, NGINX इसे फॉरवर्ड करता है, और Node काम शुरू करता है। यदि Node पर्याप्त समय तक कोई रिस्पॉन्स बाइट्स नहीं भेजता है, तो NGINX का रीड टाइमर समाप्त हो सकता है और अपस्ट्रीम कनेक्शन बंद हो सकता है, जिससे 502 या 504 उत्पन्न होता है। हो सकता है कि Node को उसी क्षण कैंसिलेशन प्राप्त न हो; वह पहले ही एक राइट कमिट कर चुका हो और फिर गणना पूरी करे। इसलिए उपयोगकर्ता-दृश्य विफलता और एक पूर्ण बिज़नेस ऑपरेशन एक साथ मौजूद हो सकते हैं।

ट्रेस, रिक्वेस्ट और जॉब आईडी के साथ NGINX एक्सेस/एरर लॉग्स, Node रिक्वेस्ट स्टार्ट/एंड/एबॉर्ट इवेंट्स, डाउनस्ट्रीम कॉल्स और डेटाबेस कमिट्स को कोरिलेट करें। upstream_response_time, हैंडलर अवधि, क्लाइंट प्राप्ति समय और साइड-इफेक्ट कमिट समय की तुलना करें। यह प्रॉक्सी आइडल टाइमआउट, एप्लिकेशन डेडलाइन, डाउनस्ट्रीम टाइमआउट और क्लाइंट डिस्कनेक्ट के बीच अंतर करता है। केवल एप्लिकेशन का "सफलता" लॉग पर्याप्त नहीं है।

NGINX का proxy_read_timeout डिफ़ॉल्ट रूप से 60 सेकंड का होता है और दो रीड्स के बीच के सबसे लंबे निष्क्रिय अंतराल को मापता है; बाइट्स प्राप्त करने पर वह अंतराल रीस्टार्ट हो जाता है। इसे बढ़ाने से प्रॉक्सी की सहनशीलता बदलती है, न कि क्लाइंट की डेडलाइन या कनेक्शन लागत। यदि आप इसे बदलते हैं, तो प्रॉक्सी, एप्लिकेशन और क्लाइंट सीमाओं को एक तालिका में दर्ज करें और रिस्पॉन्स ट्रांसमिशन, क्लीनअप और नेटवर्क जिटर के लिए समय आरक्षित करें।

Node AbortSignal.timeout() के साथ एक डेडलाइन बना सकता है और सिग्नल को fetch, डेटाबेस या SDK कॉल्स को पास कर सकता है जो कैंसिलेशन का समर्थन करते हैं। कैंसिलेशन सहयोगी (cooperative) होता है: एक लाइब्रेरी जो सिग्नल को अनदेखा करती है, वह जारी रह सकती है। पहले से कमिट किए गए ट्रांजेक्शन को एबॉर्ट करके गायब नहीं किया जा सकता है। इसलिए प्रत्येक साइड इफेक्ट के लिए एक आइडेम्पोटेंसी की, एक स्टेट मशीन या accepted, running, succeeded, failed और unknown जैसी स्पष्ट अवस्थाओं वाले क्षतिपूर्ति पथ (compensation path) की आवश्यकता होती है।

यदि जॉब का p99 इंटरैक्शन बजट से बहुत आगे है, तो एक एसिंक्रोनस सीमा बनाएं। API इनपुट को मान्य करता है, एक जॉब रिकॉर्ड या कतार संदेश लिखता है, और 202 के साथ एक जॉब आईडी लौटाता है। एक वर्कर जॉब को लीज पर लेता है, रीट्राय निष्पादित करता है और परिणाम को पर्सिस्ट करता है; क्लाइंट स्थिति के लिए पोल करता है या सदस्यता लेता है। जॉब निर्माण और समापन आइडेम्पोटेंट होना चाहिए, वर्कर रीस्टार्ट पुनर्प्राप्त करने योग्य होना चाहिए, और डुप्लिकेट डिलीवरी से भुगतान या संसाधन निर्माण की डुप्लिकेट नहीं होनी चाहिए। कतार में स्टोरेज, वर्कर्स और डेड-लेटर ऑपरेशंस जुड़ते हैं जिनके लिए क्षमता और अलर्ट की आवश्यकता होती है।

स्ट्रीमिंग केवल तभी उपयुक्त है जब परिणाम सुरक्षित रूप से टुकड़ों (chunks) में उत्पादित किए जा सकते हों, हर मध्यस्थ लंबे समय तक चलने वाले रिस्पॉन्स का समर्थन करता हो, और कुल अवधि सीमित हो। हार्टबीट्स कुल डेडलाइन, आउटपुट सीमा या कैंसिलेशन पथ की जगह नहीं लेते हैं। असीमित काम को छिपाने के लिए स्ट्रीमिंग का उपयोग न करें।

एक ज्ञात प्रॉक्सी आइडल टाइमआउट सेट करके और उससे आगे डाउनस्ट्रीम साइलेंस इंजेक्ट करके सुधार को सत्यापित करें; विभिन्न चरणों में क्लाइंट्स को डिस्कनेक्ट करें; वर्कर्स को रीस्टार्ट करें; और कॉनक्रेन्सी परीक्षण चलाएं। प्रति लॉजिकल जॉब अधिकतम एक सफल साइड इफेक्ट, डेडलाइन से परे कोई रीट्राय न होना, सीमित कनेक्शन और कतार उपयोग, और एक ट्रेस जो प्रत्येक लेयर के टाइमस्टैम्प को फिर से बना सके, की पुष्टि करें।

मॉडल उत्तर

“मैं 30 सेकंड को सीधे पांच मिनट में बदलकर शुरुआत नहीं करूँगा। पहले मैं NGINX, Node, डाउनस्ट्रीम और डेटाबेस टाइमस्टैम्प्स को कोरिलेट करूँगा ताकि यह निर्धारित किया जा सके कि प्रॉक्सी ने 502 उत्पन्न किया है या Node ने इसे लौटाया है। proxy_read_timeout रीड्स के बीच एक निष्क्रिय अंतराल है, जबकि Node रिक्वेस्ट डेडलाइन और बिज़नेस कंप्लीशन अलग-अलग घटनाएं हैं; Node के जारी रहने और साइड इफेक्ट कमिट करने के दौरान प्रॉक्सी कनेक्शन बंद कर सकता है।

एक सिंक्रोनस परिणाम के लिए, मैं एक एंड-टू-एंड डेडलाइन परिभाषित करूँगा, शेष बजट को डाउनस्ट्रीम में प्रोपेगेट करूँगा, AbortSignal.timeout() का उपयोग करूँगा, और सत्यापित करूँगा कि प्रत्येक SDK कैंसिलेशन का पालन करता है। एक अज्ञात राइट परिणाम के लिए एक आइडेम्पोटेंसी की और स्थिति लुकअप की आवश्यकता होती है। यदि जॉब का p99 इंटरैक्शन बजट से अधिक है, तो API को जॉब को पर्सिस्ट करना चाहिए और आईडी के साथ 202 लौटाना चाहिए; वर्कर्स निष्पादित करते हैं, पुनः प्रयास करते हैं और स्थिति को पर्सिस्ट करते हैं। मैं प्रॉक्सी आइडल टाइमआउट, क्लाइंट डिस्कनेक्ट, वर्कर रीस्टार्ट और डुप्लिकेट डिलीवरी को इंजेक्ट करूँगा, फिर बिना किसी डुप्लिकेट साइड इफेक्ट, सीमित कनेक्शन उपयोग और एक पूर्ण ट्रेस की जांच करूँगा।”

सामान्य गलतियाँ

  • केवल NGINX टाइमआउट बढ़ाना → लंबे कनेक्शन और कॉनक्रेन्सी का दबाव बना रहता है → एक बिज़नेस डेडलाइन और एसिंक सीमा परिभाषित करें।
  • प्रत्येक 502 का पुनः प्रयास करना → मूल जॉब कमिट हो चुकी हो सकती है → स्थिति की जांच करें और आइडेम्पोटेंसी की का पुन: उपयोग करें।
  • proxy_read_timeout को कुल रिस्पॉन्स समय मानना → छोटे निरंतर चंक्स एक रिक्वेस्ट को अनिश्चित काल तक जीवित रख सकते हैं → एक कुल डेडलाइन और आउटपुट कैप जोड़ें।
  • यह मान लेना कि क्लाइंट क्लोज़ Node को रोक देता है → कई लाइब्रेरीज़ कैंसिलेशन को अनदेखा करती हैं → प्रति लेयर एबॉर्ट, कनेक्शन और ट्रांजेक्शन व्यवहार को सत्यापित करें।
  • असीमित जॉब को छिपाने के लिए हार्टबीट्स का उपयोग करना → संसाधन अभी भी लीक होते हैं → कुल समय, बाइट्स और कॉनक्रेन्सी को सीमित करें।
  • एक सिंक्रोनस हैंडलर में 35-सेकंड की जॉब चलाना → HTTP कनेक्शन सारा काम ढोते हैं → एक जॉब को पर्सिस्ट करें और वर्कर्स का उपयोग करें।
  • केवल Node लॉग्स को देखना → प्रॉक्सी की एरर और टाइमिंग गायब हो जाती है → प्रॉक्सी एक्सेस/एरर और अपस्ट्रीम टाइमिंग्स एकत्र करें।
  • आइडेम्पोटेंट स्थिति के बिना एक कतार जोड़ना → डुप्लिकेट डिलीवरी से डुप्लिकेट शुल्क लगते हैं → एक यूनिक जॉब की और सशर्त स्थिति अपडेट का उपयोग करें।

फॉलो-अप प्रश्न और उत्तर

फॉलो-अप 1: क्या proxy_read_timeout को 60 सेकंड में बदलना पर्याप्त है?

नहीं। यह केवल रीड्स के बीच निष्क्रिय समय को नियंत्रित करता है; किसी अन्य लेयर की डेडलाइन छोटी हो सकती है, और कनेक्शन अभी भी संसाधनों की खपत करता है। पहले इंटरैक्शन बजट परिभाषित करें, फिर हर लेयर को संरेखित करें।

फॉलो-अप 2: क्लाइंट के डिस्कनेक्ट होने के बाद Node कैसे रुकता है?

रिक्वेस्ट क्लोज़ इवेंट को ऑब्जर्व करें, एक कंट्रोलर को एबॉर्ट करें, और इसके सिग्नल को कैंसिलेबल ऑपरेशन्स को पास करें। गैर-कैंसिलेबल कॉल्स के लिए, क्षमता को अलग करें और देर से आने वाले परिणामों को सुरक्षित रूप से डिस्कार्ड करें। कमिट किए गए साइड इफेक्ट्स के लिए अभी भी आइडेम्पोटेंसी और सामंजस्य (reconciliation) की आवश्यकता होती है।

फॉलो-अप 3: स्ट्रीमिंग कब उपयुक्त है?

जब परिणाम सुरक्षित रूप से चंक किए जा सकते हैं, सभी मध्यस्थ लंबे समय तक चलने वाले रिस्पॉन्स का समर्थन करते हैं, और कुल अवधि सीमित होती है। एक हार्टबीट अंतराल, कुल डेडलाइन, आउटपुट सीमा और कैंसिलेशन पथ बनाए रखें।

फॉलो-अप 4: एक कतार डुप्लिकेट निष्पादन से कैसे बचती है?

बिज़नेस रिक्वेस्ट से एक जॉब की बनाएं और स्टोरेज में विशिष्टता लागू करें। वर्कर्स लीज का उपयोग करते हैं, समापन सशर्त अपडेट का उपयोग करता है, और बाहरी साइड इफेक्ट्स उसी आइडेम्पोटेंसी की का पुन: उपयोग करते हैं।

फॉलो-अप 5: आप कैसे साबित करते हैं कि सुधार काम करता है?

स्टेजिंग में प्रॉक्सी आइडल टाइमआउट, धीमे डाउनस्ट्रीम रिस्पॉन्स, क्लाइंट डिस्कनेक्ट, नेटवर्क रीसेट और वर्कर रीस्टार्ट इंजेक्ट करें। लेयर टाइमस्टैम्प्स की तुलना करें और एरर स्रोत, कनेक्शन उपयोग, डुप्लिकेट प्रभाव और कतार विलंब का निरीक्षण करें।

फॉलो-अप 6: जब उपयोगकर्ता को 502 मिलता है तो एप्लिकेशन लॉग सफलता क्यों कह सकते हैं?

प्रॉक्सी ने पहले कनेक्शन बंद कर दिया होगा, या रिस्पॉन्स बाद में खो गया होगा। एक समापन लॉग यह साबित करता है कि कोड समाप्त हो गया, यह नहीं कि रिस्पॉन्स डिलीवर हो गया था। प्रॉक्सी स्थिति, Node राइट परिणाम और क्लाइंट अवलोकन को कोरिलेट करें।

फॉलो-अप 7: एसिंक्रोनस निष्पादन की क्या लागत होती है?

यह स्टेट स्टोरेज, वर्कर्स, रीट्राय, डेड लेटर्स और इवेंचुअल कंसिस्टेंसी को जोड़ता है। इसके बदले में, HTTP लाइफटाइम जॉब की अवधि से अलग हो जाता है और कॉनक्रेन्सी तथा रीप्ले को स्वतंत्र रूप से नियंत्रित किया जा सकता है।

सार्वजनिक स्रोत

संबंधित प्रश्न