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

RPCs में डेडलाइन प्रोपेगेशन (deadline propagation) और कैंसिलेशन (cancellation) कैसे काम करना चाहिए?

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

प्रश्न

एक रिक्वेस्ट का बजट 2 सेकंड है और यह कई सर्विसेज को कॉल करता है। आप डेडलाइन और कैंसिलेशन को कैसे प्रोपेगेट करते हैं ताकि डाउनस्ट्रीम काम रिक्वेस्ट से अधिक समय तक न चले?

प्रश्न और दायरा (Scope)

आप एक रिक्वेस्ट पाथ डिज़ाइन कर रहे हैं जिसमें सर्विस A, B को कॉल करती है और B, C को कॉल करती है। क्लाइंट स्वीकृति से लेकर प्रतिक्रिया (response) तक 2 सेकंड की अनुमति देता है। B को कॉल करने से पहले A 500 ms खर्च कर सकता है; B, C को और एक गैर-महत्वपूर्ण (non-critical) ऑडिट सर्विस को कॉल कर सकता है। डेडलाइन, कैंसिलेशन, रीट्राई और ऑब्जर्वेबिलिटी के लिए कॉन्ट्रैक्ट की व्याख्या करें।

मान लें कि प्रत्येक हॉप स्वतंत्र रूप से विफल हो सकता है, घड़ियां (clocks) पूरी तरह से सिंक्रोनाइज़ नहीं हैं, और टाइम-आउट वाले केवल-पढ़ने योग्य (read-only) RPC को केवल तभी रीट्राई किया जा सकता है जब ऑपरेशन इडेम्पोटेंट (idempotent) हो। लक्ष्य प्रतिक्रिया के सीरियलाइज़ेशन और ट्रांसपोर्ट के लिए पर्याप्त बजट सुरक्षित रखते हुए बर्बाद होने वाले काम को रोकना है।

इंटरव्यूअर क्या जांच रहा है

InterviewStack का स्टाफ-स्तरीय सिस्टम-डिज़ाइन रूब्रिक उम्मीदवारों से लेटेंसी और विफलता बाधाओं को स्पष्ट करने, अड़चनों (bottlenecks) की पहचान करने और ट्रेड-ऑफ को सही ठहराने की अपेक्षा करता है। एक मजबूत उत्तर उन संकेतों को एक स्पष्ट बजट कॉन्ट्रैक्ट में बदल देता है:

  • एज (edge) पर एक एब्सोल्यूट रिक्वेस्ट डेडलाइन स्थापित की जाती है; प्रत्येक हॉप एक नया टाइमआउट बनाने के बजाय अपना शेष बजट प्राप्त करता है।
  • कैंसिलेशन कॉल ट्री का अनुसरण करता है, जिसमें हेज्ड (hedged) या समानांतर (parallel) शाखाएं शामिल हैं, ताकि एक पूर्ण प्रतिक्रिया उस काम को रोक दे जो अब उपयोगी नहीं है।
  • रीट्राई उसी शेष बजट का उपभोग करते हैं और इडेम्पोटेंसी तथा प्रयास सीमा (attempt cap) द्वारा प्रतिबंधित होते हैं।
  • मेट्रिक्स डेडलाइन की समाप्ति, कॉलर कैंसिलेशन, कतार विलंब (queue delay), डाउनस्ट्रीम अस्वीकृति और कैंसिलेशन के बाद पूरे किए गए उपयोगी कार्य के बीच अंतर करते हैं।

उत्तर देने से पहले स्पष्ट करने वाले प्रश्न

  1. क्या 2-सेकंड की सीमा एक उपयोगकर्ता-दृश्यमान (user-visible) SLO है या एक सख्त शुद्धता डेडलाइन (hard correctness deadline)? एक सख्त डेडलाइन देर से आने वाले परिणामों को अमान्य बनाती है; एक SLO सावधानीपूर्वक सीमित पृष्ठभूमि पूर्णता पथ (background completion path) की अनुमति देता है।
  2. प्रतिक्रिया के लिए कौन सी कॉल्स महत्वपूर्ण हैं? गैर-महत्वपूर्ण ऑडिट या अनुशंसा कॉल्स को अलग किया जा सकता है, सैंपल किया जा सकता है, या डीग्रेडेड रिस्पांस के साथ लौटाया जा सकता है; बिलिंग प्राधिकरण को नहीं।
  3. क्या राइट्स (writes) इडेम्पोटेंट हैं? रीट्राई बजट एक रीड या इडेम्पोटेंसी-की वाले कमांड के लिए सुरक्षित है, लेकिन असुरक्षित साइड इफेक्ट के लिए नहीं।
  4. क्या RPC स्टैक संदर्भ (context) को स्वचालित रूप से प्रोपेगेट करता है? यदि नहीं, तो एक इंटरसेप्टर या मिडलवेयर कॉन्ट्रैक्ट को परिभाषित करें और प्रत्येक भाषा सीमा पर इसका परीक्षण करें।
  5. क्या हमें कैंसिलेशन के बाद काम पूरा करने की आवश्यकता है, जैसे कि चेकपॉइंटेड एक्सपोर्ट? उस अपवाद के लिए कैंसिलेशन को चुपचाप अनदेखा करने के बजाय एक टिकाऊ जॉब कॉन्ट्रैक्ट (durable job contract) की आवश्यकता होती है।

30-सेकंड का उत्तर ढांचा (Framework)

"मैं इनग्रेस (ingress) पर एक डेडलाइन सेट करता हूं और RPC संदर्भ के माध्यम से शेष बजट को आगे ले जाता हूं। प्रत्येक सर्विस कतारबद्ध (queueing) होने से पहले और लंबे काम के दौरान कैंसिलेशन की जांच करती है, फिर एक छोटा चाइल्ड बजट पास करती है जो रिस्पांस और नेटवर्क स्लैक छोड़ता है। रीट्राई केवल शेष समय का उपयोग करते हैं, सीमित होते हैं, और उनके लिए इडेम्पोटेंसी आवश्यक होती है। जब कॉलर को परिणाम मिलता है या वह कैंसिल करता है, तो कैंसिलेशन सिग्नल प्रत्येक शाखा में फैन-आउट (fan-out) हो जाता है। मैं डेडलाइन-एक्सीडेड दर, प्रत्येक हॉप पर शेष बजट, कतार समय, कैंसिलेशन लेटेंसी और देर से होने वाले काम को मापता हूं, फिर चेन का लोड-टेस्ट करता हूं और धीमी या कैंसिल की गई डिपेंडेंसीज को इंजेक्ट करता हूं।"

चरण-दर-चरण गहन उत्तर

1. बजट स्थापित और प्रस्तुत करना

एज एक एब्सोल्यूट डेडलाइन रिकॉर्ड करता है, उदाहरण के लिए t0 + 2s। इसे समय के एक बिंदु के रूप में मानने से प्रत्येक हॉप चुपचाप अन्य 2 सेकंड जोड़ने से बचता है। एक सर्विस remaining = deadline - now की गणना करती है और सीरियलाइज़ेशन तथा नेटवर्क ट्रांजिट के लिए एक छोटा स्थानीय मार्जिन आरक्षित करती है। मार्जिन एक नीति है, कोई सार्वभौमिक स्थिरांक नहीं; इसे पर्सेंटाइल लेटेंसी डेटा के साथ मान्य करें।

gRPC मार्गदर्शन एक डेडलाइन को टाइमआउट से अलग करता है और स्पष्ट क्लाइंट डेडलाइन की सिफारिश करता है। यह प्रोपेगेटेड डेडलाइन को शेष समय में भी परिवर्तित करता है ताकि क्लॉक स्केव (clock skew) किसी डाउनस्ट्रीम सर्वर को मूल बजट से अधिक प्रतीक्षा न कराए। इसलिए वायर कॉन्ट्रैक्ट को RPC लाइब्रेरी के माध्यम से डेडलाइन संदर्भ को ले जाना चाहिए, न कि एक फ्री-फॉर्म एप्लिकेशन हेडर के माध्यम से जिसे कॉलर भूल सकते हैं।

2. क्रिटिकल पाथ द्वारा बजट खर्च करना

मान लीजिए कि A ने 500 ms खर्च किए। यह B को अधिकतम 1.5 सेकंड अग्रेषित करता है। यदि B को 400 ms के स्थानीय कार्य की आवश्यकता है और वह C को कॉल करता है, तो B अपने शेष बजट में से 100 ms प्रतिक्रिया मार्जिन घटाकर और C की सेवा-विशिष्ट ऊपरी सीमा में से जो भी कम हो, उसे अग्रेषित करता है। समानांतर कॉल्स समान पैरेंट डेडलाइन साझा करती हैं; वे प्रत्येक पूरे 1.5 सेकंड प्राप्त नहीं करती हैं।

कतार प्रवेश (queue admission) शेष बजट की जांच करता है। यदि अनुमानित कतार विलंब पहले से ही इससे अधिक है, तो तेजी से अस्वीकार (reject fast) करें या एक प्रलेखित डीग्रेडेड प्रतिक्रिया लौटाएं। यह सफलता असंभव होने के बाद किसी अनुरोध को वर्कर पर कब्जा करने से रोकता है।

3. केवल समाप्ति ही नहीं, कैंसिलेशन को भी प्रोपेगेट करें

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

Google SRE चेतावनी देता है कि जब कोई गहरा कॉल समय से पहले विफल हो जाता है, तो केवल डेडलाइन प्रोपेगेशन अभी भी काम को लीक कर सकता है। कैंसिलेशन को वापस ऊपर जाना चाहिए और सिबलिंग्स में फैलना (fan-out) चाहिए। एक चेकपॉइंटेड, ड्यूरेबल जॉब एक सुरक्षित चेकपॉइंट को समाप्त कर सकता है, लेकिन वह अपने स्वयं के स्टेटस API के साथ एक स्पष्ट एसिंक्रोनस वर्कफ़्लो है, न कि एक सिंक्रोनस RPC जो कैंसिलेशन को अनदेखा करता है।

4. रीट्राई को बजट-सचेत (budget-aware) बनाएं

attempt_deadline = min(parent_remaining - response_margin, per-attempt_cap) की गणना करें। जब अगला प्रयास पैरेंट डेडलाइन से पहले समाप्त नहीं हो सकता है, तो रुकें। केवल क्षणिक (transient) विफलताओं और केवल उन ऑपरेशनों को रीट्राई करें जो स्वाभाविक रूप से इडेम्पोटेंट हैं या इडेम्पोटेंसी की द्वारा सुरक्षित हैं। हेज्ड रिक्वेस्ट्स समान पैरेंट बजट का उपयोग करती हैं और एक स्वीकार्य प्रतिक्रिया आते ही हारने वाले प्रयासों को कैंसिल कर देती हैं।

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

5. ऑब्जर्वेबल विफलता सिमेंटिक्स को परिभाषित करें

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

तीन-हॉप इंटीग्रेशन हार्नेस के साथ कॉन्ट्रैक्ट का परीक्षण करें: C को शेष बजट से आगे विलंबित करें, B के कतारबद्ध होने के दौरान A पर कैंसिल करें, पहले हेज को सफल बनाएं, और क्लॉक ऑफसेट इंजेक्ट करें। पुष्टि (assert) करें कि स्पष्ट रूप से घोषित चेकपॉइंट को छोड़कर कोई भी चाइल्ड पैरेंट डेडलाइन से आगे नहीं चलता है, रीट्राई रुक जाते हैं, और परमिट जारी किए जाते हैं।

उच्च-गुणवत्ता वाला नमूना उत्तर

"मैं इनग्रेस को 2-सेकंड की डेडलाइन का एकमात्र स्वामी बनाऊंगा। A इसे RPC संदर्भ में प्राप्त करता है, और 500 ms के बाद यह शेष बजट को B को अग्रेषित करता है। B, C को कॉल करने से पहले अपना स्वयं का प्रतिक्रिया मार्जिन घटाता है; समानांतर शाखाएं अभी भी समान पैरेंट डेडलाइन साझा करती हैं। प्रत्येक चाइल्ड कतारबद्ध होने से पहले और सीमित कार्य करते समय कैंसिलेशन का निरीक्षण करता है, और जब क्लाइंट डिस्कनेक्ट होता है या कोई हेज जीतता है तो कैंसिलेशन फैल जाता है। रीट्राई शेष बजट तक सीमित हैं और उनके लिए इडेम्पोटेंसी आवश्यक है। एक देर से आने वाली ऑडिट कॉल को एक ड्यूरेबल जॉब में अलग किया जा सकता है, लेकिन महत्वपूर्ण प्रतिक्रिया यह दिखावा नहीं कर सकती कि देर से किया गया काम उपयोगी है। मैं इंजेक्ट की गई धीमी डिपेंडेंसीज, कतार विलंब, कैंसिलेशन रेस, क्लॉक स्केव और प्रत्येक हॉप पर बजट दिखाने वाले ट्रेस के साथ कॉन्ट्रैक्ट को सिद्ध करूंगा।"

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

  • प्रत्येक हॉप को एक नया टाइमआउट देना → कॉल ट्री उपयोगकर्ता बजट के N गुना समय तक चल सकता है → एक डेडलाइन प्रोपेगेट करें और शेष समय की गणना करें।
  • समाप्ति को प्रोपेगेट करना लेकिन कॉलर कैंसिलेशन को अनदेखा करना → हेज्ड और छोड़े गए अनुरोध वर्कर्स का उपभोग करते रहते हैं → कैंसिलेशन संदर्भ को फैन-आउट करें और स्टॉप लेटेंसी को मापें।
  • प्रत्येक टाइमआउट को रीट्राई करना → गैर-इडेम्पोटेंट राइट्स साइड इफेक्ट्स को दोहरा सकते हैं और समाप्त हो चुके रीट्राई लोड को बढ़ाते हैं → इडेम्पोटेंसी की आवश्यकता रखें, त्रुटियों को वर्गीकृत करें, और शेष बजट द्वारा प्रयासों को सीमित करें।
  • बजट की जांच करने से पहले कतारबद्ध करना → एक विफल होने वाला अनुरोध दुर्लभ क्षमता पर कब्जा कर लेता है → जब कतार विलंब शेष समय में फिट नहीं हो सकता है तो अस्वीकार या डीग्रेड करें।
  • माप के बिना एक निश्चित मार्जिन का उपयोग करना → बड़े पेलोड लगातार विफल होते हैं या लेटेंसी स्लैक बर्बाद होता है → ट्रांसपोर्ट और सीरियलाइज़ेशन पर्सेंटाइल से मार्जिन प्राप्त करें।
  • देर से किए गए कार्य को सफलता के रूप में छिपाना → संसाधन लीक होने के दौरान डैशबोर्ड स्वस्थ प्रतिक्रियाएं दिखाते हैं → सिंक्रोनस डेडलाइन्स को स्पष्ट चेकपॉइंटेड जॉब्स से अलग करें।

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

क्या होगा यदि सर्विसेज के बीच घड़ियां भिन्न हों?

स्वतंत्र मशीनों से प्राप्त रॉ वॉल-क्लॉक टाइमस्टैम्प की तुलना न करें। RPC लाइब्रेरी के शेष-समय रूपांतरण का उपयोग करें या बीते हुए समय को घटाने के बाद टाइमआउट को प्रोपेगेट करें। टेस्ट हार्नेस में क्लॉक-ऑफसेट परीक्षण जोड़ें।

क्या कभी डाउनस्ट्रीम में डेडलाइन बढ़ाई जानी चाहिए?

केवल उत्पाद कॉन्ट्रैक्ट को एक एसिंक्रोनस जॉब में बदलकर। एक सिंक्रोनस चाइल्ड डेडलाइन का विस्तार पैरेंट की देर से आने वाली प्रतिक्रिया को मान्य नहीं बना सकता है; यह केवल व्यर्थ के काम को बढ़ाता है।

आप धीमे पेलोड के लिए बजट कैसे आरक्षित करते हैं?

सीरियलाइज़ेशन और नेटवर्क टेल्स को अलग-अलग मापें, एक सीमित मार्जिन आरक्षित करें, और पेलोड आकार को सीमित करें या स्ट्रीमिंग का उपयोग करें। यदि मार्जिन बार-बार बजट का उपभोग करता है, तो चुपचाप प्रत्येक टाइमआउट को बढ़ाने के बजाय SLO या प्रतिक्रिया आकार (response shape) को बदलें।

कैंसिलेशन के बाद क्या बचता है?

केवल स्पष्ट रूप से टिकाऊ (durable), इडेम्पोटेंट कार्य जैसे चेकपॉइंट राइट या ऑडिट इवेंट। यह एक जॉब आइडेंटिफायर के तहत देखने योग्य होना चाहिए और इसे सिंक्रोनस रिक्वेस्ट के वर्कर या कनेक्शन को रोक कर नहीं रखना चाहिए।

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

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