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

बैकएंड इंटरव्यू: आप gRPC डेडलाइन और कैंसलेशन का प्रोपेगेशन कैसे करते हैं?

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

प्रश्न

एक API अनुरोध क्रम में तीन gRPC सेवाओं को कॉल करता है, और उपयोगकर्ता बीच में ही छोड़कर जा सकता है। डेडलाइन, कैंसलेशन, रीट्राय और सर्वर क्लीनअप व्यवहार को डिज़ाइन करें। बताएं कि चाइल्ड कॉल पेरेंट बजट के भीतर कैसे रहती हैं, स्ट्रीमिंग RPCs कैसे समाप्त होती हैं, और कैंसलेशन के बाद कोई राइट अपने परिणाम की पुष्टि कैसे करता है।

प्रॉम्प्ट और संदर्भ

एक API अनुरोध क्रम में यूजर, कैटलॉग और रिकमेंडेशन gRPC सेवाओं को कॉल करता है। जब कोई रिकमेंडेशन कॉल धीमी हो, तो उपयोगकर्ता बीच में ही कहीं और नेविगेट कर सकता है। सिस्टम को एंड-टू-एंड लेटेंसी को सीमित करना होगा, सर्वर संसाधनों को मुक्त करना होगा, रीट्राय प्रवर्धन (amplification) से बचना होगा, और किसी बाहरी साइड इफेक्ट के बाद कैंसलेशन होने पर राइट्स को क्वेरी करने योग्य बनाए रखना होगा।

gRPC गाइड डेडलाइन को क्लाइंट के प्रतीक्षा करने की ऊपरी सीमा के रूप में परिभाषित करते हैं और DEADLINE_EXCEEDED का वर्णन करते हैं; कैंसलेशन उस RPC को समाप्त करता है जिसकी अब आवश्यकता नहीं है। एक बेहतरीन उत्तर प्रत्येक लेयर को स्वतंत्र पांच सेकंड का टाइमआउट सौंपने के बजाय बजट प्रोपेगेशन, रीट्राय सीमाओं, स्ट्रीम क्लीनअप और अज्ञात परिणामों को अलग करता है।

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

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

स्पष्टीकरण के लिए प्रश्न

  • टॉप-लेवल SLO, क्लाइंट डेडलाइन और आंशिक-परिणाम नीति क्या हैं?
  • क्या तीनों कॉल केवल पढ़ने (read-only) के लिए हैं, या उनमें भुगतान और अन्य साइड इफेक्ट्स शामिल हैं?
  • कौन से स्टेटस पुनः प्रयास करने योग्य (retryable) हैं, और क्या कोई आइडम्पोटेंसी कुंजी है?
  • क्या स्ट्रीम संदेशों को फिर से चलाया (replayed) जा सकता है, और क्या कोई कर्सर या सीक्वेंस नंबर है?
  • क्या डेटाबेस और बाहरी APIs कैंसलेशन स्वीकार करते हैं?
  • कैंसलेशन के बाद, क्या अनुबंध स्टेटस लुकअप, कम्पेनसेशन, या रिकॉन्सिलीएशन का है?

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

"एज पर एक एब्सोल्यूट डेडलाइन बनाएं; चाइल्ड केवल शेष बजट इनहेरिट करते हैं। हर RPC, डेटाबेस और कैंसल करने योग्य वर्कर तक कैंसलेशन का प्रोपेगेशन करें। प्रयास सीमा, बैकऑफ़, जिटर और समान कुल डेडलाइन के साथ केवल सुरक्षित क्षणिक विफलताओं का पुनः प्रयास करें। राइट्स एक ऑपरेशन ID या स्टेटस लुकअप का उपयोग करते हैं, न कि एक नए अंधाधुंध रीट्राय का। स्ट्रीमिंग कॉल इटरेटर और कनेक्शन बंद कर देते हैं, और लॉग शेष बजट, कैंसलेशन का कारण, प्रयास और अंतिम स्टेटस रिकॉर्ड करते हैं।"

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

चरण 1: एंड-टू-एंड समय बजट परिभाषित करें

क्लाइंट डेडलाइन को ऊपरी सीमा के रूप में मानें। प्रत्येक सेवा remaining = deadline - now की गणना करती है, चाइल्ड डेडलाइन को उस बिंदु से बाद का नहीं सेट करती है, और कतारबद्ध करने, सीरियलाइजेशन और प्रतिक्रिया से निपटने के लिए समय सुरक्षित रखती है।

text
parent_deadline = 2.0s from request start
child_deadline = min(parent_deadline, now + remaining_budget)

प्रत्येक लेयर को अन्य दो सेकंड न दें: तीन-हॉप श्रृंखला छह सेकंड से अधिक हो सकती है। कतार और कार्य माप के लिए स्थानीय रूप से मोनोटोनिक क्लॉक का उपयोग करें जबकि RPC फ्रेमवर्क डेडलाइन को ले जाता है।

चरण 2: कैंसलेशन का प्रोपेगेशन करें और कार्य रोकें

नेविगेशन, स्पष्ट कैंसल और डेडलाइन समाप्ति सर्वर हैंडलर तक पहुंचनी चाहिए। हैंडलर के कैंसलेशन टोकन को डेटाबेस, HTTP क्लाइंट, कतार प्रतीक्षा और स्ट्रीम इटरेटर को पास करें। बैकग्राउंड कार्य जारी रहने के दौरान त्रुटि लौटाना एक संसाधन रिसाव (resource leak) है।

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

चरण 3: शेष बजट के भीतर पुनः प्रयास करें

अधिकतम प्रयासों, घातीय बैकऑफ़ और जिटर के साथ केवल UNAVAILABLE जैसी स्पष्ट रूप से क्षणिक त्रुटियों का पुनः प्रयास करें। प्रत्येक प्रयास समान डेडलाइन का उपयोग करता है; समाप्ति शेष रीट्राय को छोड़ देती है।

text
for attempt in 1..maxAttempts:
  if remaining(deadline) <= backoff: stop
  result = call(child, deadline, cancellation)
  if result is success or permanent_error: return result
  sleep(jittered_backoff, cancellation)
return DEADLINE_EXCEEDED

कॉल श्रृंखला में एक रीट्राय ओनर चुनें। रीट्राय प्रवर्धन और प्रति-लेयर प्रयासों को ट्रैक करें ताकि एक प्रॉक्सी और एक क्लाइंट काम को कई गुना न बढ़ाएं।

चरण 4: रीड्स को राइट्स से अलग करें

अनुबंध की अनुमति होने पर रीड्स पुनः प्रयास कर सकते हैं। राइट्स के लिए एक ऑपरेशन ID, एक यूनिक कंस्ट्रेंट और एक स्टेटस लुकअप की आवश्यकता होती है। यदि बाहरी राइट के बाद कैंसलेशन होता है, तो कॉलर के पास एक UNKNOWN परिणाम होता है और उसे तुरंत एक नई ID नहीं बनानी चाहिए।

text
PENDING -> CONFIRMED
       \-> FAILED
       \-> UNKNOWN (reconcile before retry)

स्टेटस एंडपॉइंट प्राधिकारी का परिणाम लौटाता है। एक डेडलाइन प्रतीक्षा को नियंत्रित करती है; यह सिस्टम के पार एक ऑटोमिक रोलबैक नहीं बनाती है।

चरण 5: स्ट्रीमिंग RPC लाइफसाइकिल को संभालें

एक कुल डेडलाइन और जहां उपयुक्त हो, एक निष्क्रिय टाइमआउट (idle timeout) सेट करें। प्रत्येक रीड पर कैंसलेशन की जाँच करें। जब क्लाइंट चला जाता है, तो जेनरेशन बंद करें और डेटाबेस कर्सर या सब्सक्रिप्शन बंद करें। शुरुआत से साइड इफेक्ट्स को फिर से चलाने के बजाय कर्सर या सीक्वेंस नंबर के साथ पुनः कनेक्ट करें।

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

चरण 6: प्रोपेगेशन और संसाधन सीमाओं को सत्यापित करें

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

संवेदनशील पेलोड के बिना RPC मेथड, ट्रेस ID, शेष डेडलाइन, प्रयास, स्टेटस, कैंसलेशन स्रोत और ऑपरेशन ID रिकॉर्ड करें। लोड टेस्ट को केवल औसत सफलता के बजाय कनेक्शन, कतारों, रीट्राय प्रवर्धन, CPU और टेल लेटेंसी का अवलोकन करना चाहिए।

मॉडल उत्तर

"मैं एज पर एक एब्सोल्यूट डेडलाइन बनाता हूं और शेष बजट को तीनों सेवाओं में प्रोपेगेट करता हूं। प्रत्येक हैंडलर कैंसलेशन को अपने डेटाबेस, HTTP कॉल और स्ट्रीम इटरेटर को पास करता है और वापस लौटने से पहले संसाधनों को मुक्त करता है। रीड कॉल केवल सुरक्षित क्षणिक त्रुटियों का पुनः प्रयास करती हैं, एक कुल डेडलाइन और सीमित जिटर के साथ।"

"राइट्स में एक ऑपरेशन ID होती है; कैंसलेशन के बाद मैं परिणाम को UNKNOWN के रूप में चिह्नित करता हूं और स्टेटस क्वेरी करता हूं। स्ट्रीम्स कुल डेडलाइन, कर्सर और रीकनेक्ट पॉलिसी का उपयोग करती हैं। मैं पेरेंट कैंसलेशन, चाइल्ड टाइमआउट, खोई हुई प्रतिक्रियाओं और ग्रेसफुल स्टॉप को इंजेक्ट करता हूं, फिर सत्यापित करता हूं कि कोई लीक या रीट्राय प्रवर्धन नहीं है।"

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

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

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

फॉलो-अप 1: क्या कोई चाइल्ड सेवा पेरेंट डेडलाइन को बढ़ा सकती है?

नहीं। यदि ऑपरेशन को अधिक समय चाहिए, तो इसे एसिंक्रोनस बनाएं और एक ऑपरेशन ID लौटाएं। एक सिंक्रोनस अनुरोध को चुपचाप बढ़ाना एज SLO को निष्फल करता है।

फॉलो-अप 2: क्या कैंसलेशन कमिट किए गए डेटाबेस ट्रांजेक्शन को पूर्ववत कर सकता है?

विश्वसनीय रूप से नहीं। यह उस कार्य को रोकता है जो शुरू या पूरा नहीं हुआ है; कमिट किए गए कार्य के लिए स्टेटस लुकअप, कम्पेनसेशन या रिकॉन्सिलीएशन की आवश्यकता होती है। API को ऑब्जर्वेबल स्टेट को उजागर करना चाहिए।

फॉलो-अप 3: आप दोहरे रीट्राय को कैसे रोकते हैं?

एक रीट्राय ओनर असाइन करें और अन्य लेयर्स को त्रुटियों का प्रोपेगेशन करने दें। प्रयास और कुल-बजट फ़ील्ड साझा करें, प्रयासों को सीमित करें, और प्रत्येक लेयर पर प्रवर्धन की निगरानी करें।

फॉलो-अप 4: क्या एक निष्क्रिय स्ट्रीम को हमेशा कैंसल किया जाना चाहिए?

एक जानबूझकर बनाई गई लंबे समय तक चलने वाली स्ट्रीम और एक छोड़ी गई स्ट्रीम के बीच अंतर करें। कुल डेडलाइन, निष्क्रिय टाइमआउट, या हार्टबीट का उपयोग करें और संसाधनों को हमेशा के लिए रखने के बजाय एक पुनः कनेक्ट करने योग्य स्थिति लौटाएं।

फॉलो-अप 5: क्या होगा यदि सर्वर डेडलाइन के बाद भी कंप्यूटिंग जारी रखता है?

हैंडलर और डाउनस्ट्रीम कार्य को कैंसलेशन-अवेयर बनाएं। जिस कार्य को कैंसल नहीं किया जा सकता है, उसे अनुरोध थ्रेड पर कब्जा रखने के बजाय एक ऑपरेशन ID और संसाधन सीमा के साथ एक सीमित बैकग्राउंड कतार में ले जाएं।

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

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