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

सिस्टम डिज़ाइन इंटरव्यू: आप Wasm Component Model प्लगइन रनटाइम को कैसे डिज़ाइन करेंगे?

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

प्रश्न

एक SaaS प्लेटफ़ॉर्म थर्ड पार्टीज़ को Rust, Go या Python में ऐसे प्लगइन्स लिखने की अनुमति देता है जो टेनेंट रिक्वेस्ट्स के भीतर ट्रांसफ़ॉर्मेशन और वैलिडेशन रन करते हैं। WIT इंटरफेस, कैपेबिलिटीज, कम्पैटिबिलिटी, रिसोर्स लिमिट्स, साइनिंग, ऑब्ज़र्वेबिलिटी और रोलबैक को कवर करते हुए एक Wasm Component Model प्लगइन रनटाइम डिज़ाइन करें।

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

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

Component Model घटकों (components), इंटरफेस और worlds के साथ इम्पोर्ट्स और एक्सपोर्ट्स का वर्णन करता है। WIT इंटरफ़ेस डेफ़िनिशन लैंग्वेज है, जबकि Canonical ABI यह परिभाषित करता है कि हायर-लेवल वैल्यूज़ भाषा की सीमाओं को कैसे पार करती हैं। इंटरव्यू यह टेस्ट करता है कि क्या आप इन मानकों को एक ऑपरेट करने योग्य मल्टी-टेनेंट प्लगइन प्लेटफ़ॉर्म में बदल सकते हैं।

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

इंटरफ़ेस और टाइप गवर्नेंस, न्यूनतम विशेषाधिकार (least privilege), इंस्टेंस आइसोलेशन, CPU और मेमोरी बजट, टाइमआउट और कैंसिलेशन, कंपोनेंट साइनिंग और प्रोवेनेंस, वर्शन कम्पैटिबिलिटी, रिप्रोड्यूसिएबिलिटी, लॉग्स और मेट्रिक्स, कैनरीज़ और रोलबैक को कवर करें।

स्पष्टीकरण के लिए पूछे जाने वाले प्रश्न

  • क्या कोई प्लगइन सिंक्रोनस रिक्वेस्ट के अंदर चलता है या एसिंक्रोनस जॉब के रूप में, और लेटेंसी तथा थ्रूपुट बजट क्या हैं?
  • किन फ़ाइल, नेटवर्क, की (key) या क्लॉक कैपेबिलिटीज की आवश्यकता है, और टेनेंट्स को कैसे आइसोलेट किया जाता है?
  • क्या इंटरफ़ेस resources, streams और futures का उपयोग कर सकता है, या केवल बाउंडेड वैल्यू टाइप्स का?
  • क्या अपग्रेड के बाद पुराने टेनेंट्स रिप्रोड्यूस करने योग्य रहने चाहिए, और कम्पैटिबिलिटी विंडो कितनी लंबी है?
  • क्या किसी उल्लंघन या टाइमआउट पर प्रोसेस को तुरंत समाप्त करना चाहिए, आइसोलेशन में दोबारा प्रयास (retry) करना चाहिए, या होस्ट फ़ॉलबैक का उपयोग करना चाहिए?

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

“एक संकीर्ण (narrow), वर्शनयुक्त WIT world परिभाषित करें और केवल आवश्यक व्यावसायिक क्षमताओं (business capabilities) को ही एक्सपोज़ करें। कंट्रोल प्लेन प्रोवेनेंस, सिग्नेचर और डिपेंडेंसीज़ को सत्यापित करता है; डेटा प्लेन CPU, मेमोरी, आउटपुट और डेडलाइन सीमाओं के साथ एक आइसोलेटेड Wasm इंस्टेंस चलाता है। इंटरफ़ेस कम्पैटिबिलिटी की जाँच करें और कैनरी अपग्रेड करें, साथ ही वर्शन, टेनेंट, बजट खपत और परिणाम सारांश रिकॉर्ड करें। टाइमआउट या उल्लंघन होने पर केवल वही प्लगइन रुकता है और एक सुरक्षित होस्ट डिफ़ॉल्ट रिटर्न करता है।”

स्टेप-बाय-स्टेप डीप डाइव

स्टेप 1: WIT इंटरफेस और डेटा बाउंड्रीज़ परिभाषित करें

स्पष्ट एरर enums, अधिकतम लंबाई और एन्कोडिंग के साथ बाउंडेड records, variants, lists और results को प्राथमिकता दें। होस्ट ऑब्जेक्ट्स या छिपे हुए ग्लोबल स्टेट को एक्सपोज़ न करें; प्रत्येक world में केवल उस प्लगइन क्लास के लिए आवश्यक इम्पोर्ट्स और एक्सपोर्ट्स होने चाहिए।

text
world transform-v2 {
  export transform: func(input: record { bytes: list<u8>, mime: string }) -> result<list<u8>, transform-error>
}

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

स्टेप 2: कैपेबिलिटी और टेनेंट आइसोलेशन बनाएं

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

कैपेबिलिटी टोकन कम समय के लिए वैध, ऑडिट करने योग्य और टेनेंट्स के बीच गैर-रीप्ले करने योग्य (non-replayable) होने चाहिए। होस्ट API को न्यूनतम रखें; प्लगइन को कभी भी होस्ट-प्रोसेस पॉइंटर्स या अनफ़िल्टर्ड सिस्टम हैंडल्स न दें।

स्टेप 3: बजट और टर्मिनेशन सेट करें

निर्देश (instruction) या समय बजट, लीनियर-मेमोरी सीमाएं, टेबल और स्टैक सीमाएं, आउटपुट कैप और कन्करेंसी कोटा सेट करें। एक डेडलाइन के साथ कैंसिलेशन का प्रसार करें; अपने बजट से अधिक होने वाले इंस्टेंस को समाप्त करें और इसका कारण रिकॉर्ड करें। केवल आइडम्पोटेंसी (idempotency) की जाँच करने के बाद ही तय करें कि क्या रिट्राय सुरक्षित है।

यूज़र रिक्वेस्ट के भीतर अनबाउंडेड वेटिंग रखने के बजाय लंबे जॉब्स के लिए एसिंक्रोनस कतार (queue) और लीज़ का उपयोग करें। टेनेंट और प्लगइन दोनों के आधार पर मीटर और रेट-लिमिट करें ताकि एक टेनेंट शेयर्ड एक्ज़ीक्यूशन पूल का पूरा उपभोग न कर सके।

स्टेप 4: कंपोनेंट और ABI कम्पैटिबिलिटी को संभालें

रिलीज़ से पहले, WIT world और डिपेंडेंसीज़ को पार्स करें और कम्पैटिबिलिटी नियमों के विरुद्ध इम्पोर्ट्स और एक्सपोर्ट्स की जाँच करें। Canonical ABI वैल्यू रिप्रेज़ेंटेशन को मानकीकृत करता है लेकिन व्यावसायिक कम्पैटिबिलिटी की गारंटी नहीं देता है; enum जोड़ने, बदले हुए एरर अर्थों और यूनिट परिवर्तनों के लिए अभी भी कॉन्ट्रैक्ट टेस्ट्स की आवश्यकता होती है।

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

स्टेप 5: सप्लाई चेन और लोडिंग सत्यापित करें

एक इम्यूटेबल आर्टिफ़ैक्ट डाइजेस्ट जनरेट करें और कंपोनेंट, WIT world, डिपेंडेंसी लॉकफ़ाइल और बिल्ड मेटाडेटा पर हस्ताक्षर (sign) करें। कंट्रोल प्लेन केवल विश्वसनीय हस्ताक्षरकर्ताओं और स्कैन की गई डिपेंडेंसीज़ की अनुमति देता है; लोडिंग डाइजेस्ट, सिग्नेचर, टारगेट रनटाइम वर्शन और रिवोकेशन स्थिति की दोबारा जाँच करती है।

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

स्टेप 6: ऑब्ज़र्व करें, कैनरी टेस्ट करें और रिकवर करें

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

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

एक सशक्त नमूना उत्तर

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

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

  • होस्ट ऑब्जेक्ट्स को सीधे एक्सपोज़ करना → प्रिविलेज एस्केलेशन और क्रॉस-टेनेंट लीकेज → न्यूनतम होस्ट फ़ंक्शंस का उपयोग करें।
  • मेमोरी को सीमित करना लेकिन समय को नहीं → एक इनफिनिट लूप अभी भी पूल की खपत करता है → CPU, डेडलाइन और कन्करेंसी बजट सेट करें।
  • Canonical ABI को बिज़नेस कम्पैटिबिलिटी मानना → यूनिट्स और एरर सिमेंटिक्स अभी भी कॉलर्स को तोड़ सकते हैं → कॉन्ट्रैक्ट टेस्ट्स और world वर्शन्स बनाए रखें।
  • म्यूटेबल टैग द्वारा कैशिंग करना → एक बदला हुआ टैग अज्ञात कोड चलाता है → इम्यूटेबल डाइजेस्ट और सिग्नेचर द्वारा एड्रेस करें।
  • हर विफलता पर दोबारा प्रयास (retry) करना → नॉन-आइडम्पोटेंट साइड इफेक्ट्स दोहराए जाते हैं → आइडम्पोटेंसी घोषित करें और एरर्स को वर्गीकृत करें।

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

फॉलो-अप 1: प्रोसेस या कंटेनर का उपयोग क्यों नहीं करते?

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

फॉलो-अप 2: आप बड़ी फ़ाइलों की स्ट्रीमिंग का समर्थन कैसे करते हैं?

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

फॉलो-अप 3: आप कैसे तय करते हैं कि दो वर्शन समान हैं?

शैडो एक्ज़ीक्यूशन के माध्यम से एक निश्चित इनपुट कॉर्पस चलाएं और नॉर्मलाइज़्ड परिणामों, एरर क्लासेज, लेटेंसी और रिसोर्स उपयोग की तुलना करें। घोषित फ़्लोटिंग-पॉइंट या ऑर्डरिंग अंतरों की अनुमति दें और अस्वीकार्य डेल्टास पर रिलीज़ को रोकें।

फॉलो-अप 4: क्या होगा यदि किसी प्लगइन को नेटवर्क एक्सेस की आवश्यकता हो?

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

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

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

संबंधित इंटरव्यू टूल

सिस्टम डिज़ाइन उत्तर के लिए हल करें का उपयोग करें

पहले आवश्यकताओं को स्पष्ट करें, फिर स्केल, आर्किटेक्चर, कंपोनेंट चयन और ट्रेड-ऑफ की ओर बढ़ें।

टूल देखें