प्रश्न और इसका उपयोग कब करें
3 क्षेत्रों (regions) में 20,000 सर्वर इंस्टेंसेस द्वारा उपयोग किए जाने वाले एक मल्टी-टेनेंट फ़ीचर फ़्लैग सिस्टम को डिज़ाइन करें। यह प्रोजेक्ट्स में 50,000 फ़्लैग्स को स्टोर करता है, 1 मिलीसेकंड से कम अतिरिक्त p99 लेटेंसी के साथ प्रति सेकंड 5 मिलियन इन-प्रोसेस इवैल्यूएशन को हैंडल करता है, p99 पर 5 सेकंड के भीतर पब्लिश किए गए बदलाव को प्रोपेगेट करता है, और 15-मिनट के कंट्रोल-प्लेन आउटेज के दौरान भी इवैल्यूएशन जारी रखता है। इसे टाइप्ड वेरिएशन्स, टारगेटिंग, डिटर्मिनिस्टिक पर्सेंटेज रोलआउट्स, ऑडिट लॉग्स, अप्रूवल्स और एक इमरजेंसी ऑफ़ स्विच का समर्थन करना चाहिए।
ये संख्याएं इंटरव्यू के अनुमान हैं, प्रोडक्ट बेंचमार्क नहीं। मान लें कि प्रत्येक रनटाइम अधिकतम 500 प्रासंगिक फ़्लैग्स को सब्सक्राइब करता है, एक औसत सीरियलाइज़्ड फ़्लैग डेफ़िनिशन 2 KB की है, कंट्रोल-प्लेन राइट्स 100 प्रति सेकंड के पीक पर हैं, और सर्वर-साइड इवैल्यूएशन नियमों में संवेदनशील एट्रिब्यूट्स हो सकते हैं। क्लाइंट और मोबाइल डिलीवरी, एक्सपेरिमेंटेशन स्टैटिस्टिक्स और एक जनरल-पर्पस कॉन्फ़िगरेशन सर्विस बेस रिक्वायरमेंट्स के बजाय फ़ॉलो-अप्स हैं।
यह प्रश्न सीनियर बैकएंड, प्लेटफ़ॉर्म, इंफ्रास्ट्रक्चर, रिलीज़-इंजीनियरिंग और सिस्टम-डिज़ाइन इंटरव्यूज़ के लिए उपयुक्त है। इसका पुनः प्रयोज्य (reusable) सबक यह है कि कोई सिस्टम रिक्वेस्ट पाथ को लोकल और उपलब्ध रखते हुए मैनेजमेंट पाथ को मजबूती से गवर्न कर सकता है। वह अलगाव लगभग हर बाद के विकल्प को निर्धारित करता है।
इंटरव्यूअर क्या मूल्यांकन कर रहा है
पहला संकेत यह है कि क्या कैंडिडेट डिप्लॉयमेंट को रिलीज़ से और कंट्रोल प्लेन को डेटा प्लेन से अलग करता है। एक डैशबोर्ड और डेटाबेस फ़्लैग डेफिनिशन्स को मैनेज करते हैं। एप्लिकेशन SDKs प्रोसेस के भीतर एक वर्ज़न किए गए रूलसेट का मूल्यांकन करते हैं। प्रत्येक फ़्लैग चेक के लिए एक रिमोट RPC हर प्रोडक्ट रिक्वेस्ट में एक मैनेजमेंट आउटेज और नेटवर्क लेटेंसी ला देगा।
दूसरा संकेत सिमेंटिक सटीकता है। एक फ़्लैग इवैल्यूएशन के लिए एक फ़्लैग की (flag key), एनवायरनमेंट, टाइप्ड फ़ॉलबैक और इवैल्यूएशन संदर्भ (context) की आवश्यकता होती है। ऑर्डर्ड रूल्स, स्पष्ट टारगेट्स, पर्सेंटेज एलोकेशन और डिफ़ॉल्ट रूल में डिटर्मिनिस्टिक प्राथमिकता होनी चाहिए। "अनियमित रूप से 10% रिक्वेस्ट्स को फ़ीचर दें" गलत है जब किसी यूज़र को रिक्वेस्ट्स और रीजन्स में एक स्थिर अनुभव मिलना चाहिए।
तीसरा संकेत फ़ेल्योर डिज़ाइन है। लास्ट-नोन-गुड (Last-known-good) स्टेट एक कंट्रोल-प्लेन आउटेज के दौरान इवैल्यूएशन को बनाए रखती है, लेकिन यह बासी (stale) कॉन्फ़िगरेशन को एक स्पष्ट जोखिम भी बनाती है। एक मजबूत उत्तर स्टार्टअप व्यवहार, अधिकतम स्वीकार्य पुरानापन (staleness), गैप रिकवरी, अमान्य-अपडेट रिजेक्शन, इमरजेंसी डिसेबल व्यवहार, और एक कॉस्मेटिक बदलाव बनाम एक खतरनाक राइट पाथ के लिए अलग-अलग डिफ़ॉल्ट्स को परिभाषित करता है।
चौथा संकेत ऑपरेशनल ओनरशिप है। फ़्लैग एडिट्स प्रोडक्शन बदलाव हैं। ऑथेंटिकेशन, ऑथराइज़ेशन, एनवायरनमेंट सेपरेशन, ऑप्टिमिस्टिक कंकरेंसी, वैलिडेशन, अप्रूवल पॉलिसी, इम्यूटैबल ऑडिट रिकॉर्ड्स, स्टेज्ड पब्लिकेशन, रोलबैक, ओनरशिप और रिटायरमेंट सभी डिज़ाइन का हिस्सा हैं।
उत्तर देने से पहले स्पष्ट करने योग्य प्रश्न
- इवैल्यूएशन कहाँ किया जाता है? सर्वर-साइड SDKs पूरा रूलसेट प्राप्त कर सकते हैं और स्थानीय स्तर पर मूल्यांकन कर सकते हैं। ब्राउज़र और मोबाइल क्लाइंट संवेदनशील टारगेटिंग नियमों को सुरक्षित रूप से प्राप्त नहीं कर सकते, इसलिए उन्हें एक फ़िल्टर किए गए या दूरस्थ रूप से मूल्यांकित मॉडल की आवश्यकता होती है।
- 5-सेकंड का उद्देश्य क्या मापता है? इसे एक सफल पब्लिश से लेकर उस वर्ज़न को लागू करने वाले 99% स्वस्थ सब्सक्राइब किए गए सर्वर इंस्टेंसेस तक परिभाषित करें। ऑफ़लाइन इंस्टेंसेस और समर्थित फ्रेशनेस विंडो के बाहर के क्लाइंट्स को अलग सिमेंटिक्स की आवश्यकता होती है।
- फ़ॉलबैक कॉन्ट्रैक्ट क्या है? यदि किसी SDK ने कभी कोई मान्य स्नैपशॉट लोड नहीं किया है, तो वह एप्लिकेशन कोड द्वारा प्रदान किया गया टाइप्ड डिफ़ॉल्ट लौटाता है। इनिशियलाइज़ेशन के बाद, यह सहमत बासी विंडो के लिए लास्ट-नोन-गुड वर्ज़न का उपयोग कर सकता है।
- क्या एक ही सब्जेक्ट को एक ही कोहोर्ट में रहना चाहिए? पर्सेंटेज रोलआउट के लिए एक स्थिर टारगेटिंग की और डिटर्मिनिस्टिक हैश इनपुट्स की आवश्यकता होती है। यदि स्थिरता मायने रखती है तो अनाम सेशन्स को एक टिकाऊ पहचानकर्ता की आवश्यकता होती है।
- क्या नियमों में संवेदनशील डेटा हो सकता है? सेगमेंट IDs और गैर-संवेदनशील एट्रिब्यूट्स को प्राथमिकता दें। सर्वर-साइड डिलीवरी प्रोटेक्टेड नियमों को ले जा सकती है; ब्राउज़र डिलीवरी को सीक्रेट्स, इंटरनल अलाउलिस्ट्स या ऑथराइज़ेशन लॉजिक को उजागर नहीं करना चाहिए।
- एक इमरजेंसी ऑफ़ स्विच कितना महत्वपूर्ण है? पाँच-सेकंड का प्रोपेगेशन SLO उपयोगी है लेकिन तात्कालिक नहीं है। वास्तव में विनाशकारी ऑपरेशन्स के लिए अभी भी सर्वर-साइड ऑथराइज़ेशन और स्वतंत्र सुरक्षा नियंत्रणों की आवश्यकता होती है।
30-सेकंड का उत्तर ढांचा
"मैं प्लेटफ़ॉर्म को एक गवर्न किए गए कंट्रोल प्लेन और एक लोकल इवैल्यूएशन प्लेन में विभाजित करूँगा। कंट्रोल प्लेन इम्यूटैबल स्नैपशॉट्स और पैचेस को वैलिडेट, वर्ज़न, ऑडिट और पब्लिश करता है। सर्वर SDKs अंतिम मान्य नियमों को रखते हैं और प्रोसेस में टारगेट्स, ऑर्डर्ड रूल्स, रोलआउट्स और डिफ़ॉल्ट्स का मूल्यांकन करते हैं; इनिशियलाइज़ेशन से पहले या अमान्य स्थिति पर वे कोड फ़ॉलबैक लौटाते हैं। एक डिटर्मिनिस्टिक रोलआउट एक स्थिर सब्जेक्ट की को एनवायरनमेंट, फ़्लैग की और सॉल्ट के साथ हैश करता है। स्ट्रीम्स अपडेट्स पुश करती हैं और पोलिंग गैप्स को ठीक करती है, इसलिए कंट्रोल-प्लेन आउटेज कभी भी रिक्वेस्ट पाथ में प्रवेश नहीं करता है। मैं प्रोपेगेशन, क्रॉस-SDK रिज़ल्ट्स, कोहोर्ट स्थिरता, स्टेल व्यवहार और फ़ॉल्ट्स के तहत रोलबैक का परीक्षण करूँगा।"
स्टेप-बाय-स्टेप समाधान
स्टेप 1: प्रॉम्प्ट को स्पष्ट कॉन्ट्रैक्ट्स में बदलें
कार्यात्मक आवश्यकताएं हैं फ़्लैग्स बनाना, एडिट करना, अप्रूव करना, पब्लिश करना, डिसेबल करना और रिटायर करना; बूलियन, स्ट्रिंग, नंबर, या स्ट्रक्चर्ड वेरिएशन्स को परिभाषित करना; सब्जेक्ट्स या सेगमेंट्स को टारगेट करना; प्रतिशत आवंटित करना; और डिबगिंग के लिए इवैल्यूएशन डिटेल्स लौटाना। गैर-कार्यात्मक आवश्यकताएं हैं 1 मिलीसेकंड से कम लोकल p99, 5-सेकंड p99 प्रोपेगेशन, रीजन्स में डिटर्मिनिस्टिक रिज़ल्ट्स, और 15-मिनट के मैनेजमेंट आउटेज के लिए निरंतर इवैल्यूएशन।
कंपोनेंट्स बनाने से पहले तीन सीमाएं परिभाषित करें:
- एक पब्लिश किया गया वर्ज़न इम्यूटैबल होता है। बाद का संपादन एक और ड्राफ़्ट और वर्ज़न बनाता है।
- प्रोपेगेशन SLO स्वस्थ कनेक्टेड सर्वर इंस्टेंसेस पर लागू होता है, न कि उन डिवाइसेस पर जो ऑफ़लाइन हैं।
- एप्लिकेशन अंतिम फ़ॉलबैक वैल्यू का मालिक होता है। टाइप चेकिंग, इनिशियलाइज़ेशन, या इवैल्यूएशन विफल होने पर प्लेटफ़ॉर्म कभी भी कोई वैल्यू ईजाद नहीं करता है।
बेस डिज़ाइन के लिए, लास्ट-नोन-गुड स्टेट कम से कम आवश्यक 15 मिनट के लिए मान्य रहती है। किसी फ़्लैग की पब्लिश की गई stale_after सीमा के बाद, इसका stale_action या तो निरंतर लास्ट-नोन-गुड इवैल्यूएशन या कोड फ़ॉलबैक चुनता है, और SDK एक स्टेल कारण लौटाता है। एक सुरक्षा-संवेदनशील या विनाशकारी पाथ को चुपचाप एक पुराने इनेबलमेंट नियम को सर्व करने के बजाय फ़ॉलबैक का चयन करना चाहिए।
यह इन्फ्रास्ट्रक्चर के अंदर प्रोडक्ट पॉलिसी को छिपाने से बचाता है। एक चेकआउट माइग्रेशन पुराने पाथ पर डिफ़ॉल्ट हो सकता है, जबकि एक सुरक्षा-संवेदनशील क्षमता डिसेबल होने पर डिफ़ॉल्ट हो सकती है। दोनों अलग-अलग एप्लिकेशन कॉन्ट्रैक्ट्स के साथ एक ही प्लेटफ़ॉर्म का उपयोग करते हैं।
स्टेप 2: कंट्रोल प्लेन और इवैल्यूएशन डेटा प्लेन को अलग करें
कंट्रोल प्लेन में मैनेजमेंट API और UI, आइडेंटिटी और रोल चेक्स, स्कीमा और रूल वैलिडेटर, अप्रूवल वर्कफ़्लो, रिलेशनल सोर्स ऑफ़ ट्रुथ, अपेंड-ओनली ऑडिट लॉग, स्नैपशॉट बिल्डर और पब्लिशर शामिल हैं। इवैल्यूएशन की तुलना में राइट्स कम मात्रा में होते हैं, इसलिए माइक्रोसेकंड लेटेंसी की तुलना में शुद्धता, समीक्षात्मकता (reviewability), और पुनर्प्राप्ति क्षमता (recoverability) अधिक मायने रखती है।
डेटा प्लेन में रीजनल स्ट्रीम रिले, स्नैपशॉट स्टोरेज, पोलिंग एंडपॉइंट्स, और SDK-लोकल स्टोर्स और इवैल्यूएटर्स शामिल हैं। सर्वर SDKs एक रीजनल स्ट्रीम खोलते हैं, एक इम्यूटैबल स्नैपशॉट इंस्टॉल करते हैं, वर्ज़न किए गए पैचेस लागू करते हैं, और बिना किसी नेटवर्क कॉल के इवैल्यूएशन करते हैं। यदि स्ट्रीम टूट जाती है, तो वे अंतिम मान्य स्थिति बनाए रखते हैं और जिटर (jitter) के साथ पोल करते हैं। यदि कोई पैच किसी वर्ज़न को छोड़ देता है या चेकसम वैलिडेशन में विफल रहता है, तो SDK पैच को डिस्कार्ड कर देता है और एक पूर्ण स्नैपशॉट का अनुरोध करता है।
डेटा-प्लेन डिलीवरी को प्राइमरी कंट्रोल डेटाबेस से स्वतंत्र रखें। पब्लिशर रिले को सूचित करने से पहले एक टिकाऊ वर्ज़न आर्टिफ़ैक्ट लिखता है। डेटाबेस या डैशबोर्ड आउटेज तब मौजूदा इवैल्यूएशन को रोके बिना नए एडिट्स को रोक सकता है।
स्टेप 3: डेटा मॉडल और APIs को परिभाषित करें
एक फ़्लैग डेफ़िनिशन के लिए कम से कम आवश्यकता होती है:
FlagDefinition {
tenant_id, project_id, environment, flag_key
version, value_type, variations[], off_variation
ordered_rules[], default_rule, salt
stale_after, stale_action
state, owner, expires_at
}
Rule {
rule_id, conditions[], outcome
}
Outcome = fixed_variation | weighted_variations[]सेगमेंट्स को अलग से वर्ज़न किया जाता है क्योंकि कई फ़्लैग्स एक कोहोर्ट का संदर्भ ले सकते हैं। एक ऑडिट प्रविष्टि एक्टर, समय, कारण, अपेक्षित पिछला वर्ज़न, पहले और बाद के संदर्भ, अप्रूवल और पब्लिश परिणाम रिकॉर्ड करती है। ड्राफ़्ट्स को पब्लिश किए गए आर्टिफ़ैक्ट्स से अलग रखें ताकि एक अस्वीकृत संपादन इवैल्यूएशन में लीक न हो सके।
प्रतिनिधि APIs हैं:
PUT /v1/projects/{project}/environments/{env}/flags/{key}
body: draft definition, expectedVersion
POST /v1/projects/{project}/environments/{env}/flags/{key}:publish
body: draftVersion, reason, approvalToken
GET /v1/sdk/bootstrap?project={project}&env={env}&after={version}
GET /v1/sdk/stream?project={project}&env={env}अपेक्षित वर्ज़न दो एडिटर्स को चुपचाप एक-दूसरे को ओवरराइट करने से रोकता है। मैनेजमेंट क्रेडेंशियल्स कभी भी SDK क्रेडेंशियल्स के रूप में काम नहीं करते हैं। टेनेंट, प्रोजेक्ट, एनवायरनमेंट और अनुमत डिलीवरी मोड हर ऑथराइज़ेशन निर्णय का हिस्सा हैं।
स्टेप 4: इवैल्यूएशन और पर्सेंटेज रोलआउट को डिटर्मिनिस्टिक बनाएं
SDKs में एक प्रलेखित क्रम का उपयोग करें:
- फ़्लैग के अस्तित्व, एनवायरनमेंट, टाइप और क्या टारगेटिंग सक्षम है, इसकी जांच करें।
- एक स्पष्ट सब्जेक्ट या सेगमेंट टारगेट लागू करें।
- ऑर्डर्ड रूल्स का मूल्यांकन करें; पहला मैचिंग नियम जीतता है।
- एक फिक्स्ड वेरिएशन या एक वेटेड रोलआउट को हल करें।
- जब कुछ भी मेल न खाए तो डिफ़ॉल्ट नियम का उपयोग करें।
- जब इवैल्यूएशन एक मान्य टाइप्ड रिज़ल्ट नहीं दे सकता है, तो एक एरर कारण के साथ एप्लिकेशन फ़ॉलबैक लौटाएं।
एक वेटेड रोलआउट के लिए, स्थिर इनपुट्स से एक बकेट प्राप्त करें:
bucket = H(tenant_id || environment || flag_key || salt || targeting_key) mod 100000बकेट को संचयी (cumulative) वेरिएशन रेंजेस में मैप करें। समान इनपुट्स हर इंस्टेंस और रीजन पर समान परिणाम उत्पन्न करते हैं। पब्लिश की गई परिभाषा में सॉल्ट और एल्गोरिदम वर्ज़न को रखने से व्यवहार पुनरुत्पादक (reproducible) बनता है। एक मौजूदा सन्निहित (contiguous) रेंज का विस्तार करने से उसके अंदर पहले से मौजूद सब्जेक्ट्स को सुरक्षित रखा जा सकता है, लेकिन मनमाना रीवेटिंग या हैश इनपुट्स को बदलने से यूज़र्स स्थानांतरित हो सकते हैं; समीक्षा के दौरान उस परिणाम को उजागर करें।
समान प्रतिशत वाले दो स्वतंत्र फ़्लैग्स को समान सब्जेक्ट्स का चयन करने की आवश्यकता नहीं है क्योंकि फ़्लैग की हैशिंग में भाग लेती है। यदि कई फ़्लैग्स को एक कोहोर्ट के रूप में स्थानांतरित होना चाहिए, तो एक साझा वर्ज़न किए गए सेगमेंट को टारगेट करें या एक स्पष्ट एक्सपेरिमेंट की का उपयोग करें। जब एक स्थिर सब्जेक्ट ID मौजूद हो तो ईमेल जैसे म्यूटैबल फ़ील्ड्स को कभी भी हैश न करें।
स्टेप 5: स्नैपशॉट्स और इंक्रीमेंटल बदलावों को सुरक्षित रूप से डिलीवर करें
स्नैपशॉट बिल्डर प्रोजेक्ट और एनवायरनमेंट स्कोप को हल करता है, संदर्भित सेगमेंट्स और पूर्वापेक्षाओं (prerequisites) को मान्य करता है, नियमों को डिटर्मिनिस्टिक रूप से सॉर्ट करता है, एक विहित (canonical) आर्टिफ़ैक्ट को सीरियलाइज़ करता है, और एक वर्ज़न और चेकसम जोड़ता है। एक ट्रांजेक्शन पब्लिश किए गए मेटाडेटा और एक आउटबॉक्स रिकॉर्ड को कमिट करता है; एक एसिंक्रोनस पब्लिशर आर्टिफ़ैक्ट को स्टोर करता है और इसे रीजनल रिले को घोषित करता है। यह किसी फ़्लैग की डिलीवरी शेड्यूल किए बिना उसे कमिट करने से बचाता है।
एक SDK बूट अनुक्रम है:
- कॉन्फ़िगर होने पर एक मान्य पर्सिस्टेंट लास्ट-नोन-गुड स्नैपशॉट लोड करें।
- निकटतम रिले से नवीनतम पूर्ण या डेल्टा आर्टिफ़ैक्ट प्राप्त करें।
- केवल टाइप, वर्ज़न और चेकसम जांच के बाद इन-मेमोरी स्नैपशॉट को परमाणु (atomically) रूप से बदलें।
- प्रोवाइडर को तैयार चिह्नित करें, फिर स्थानीय इवैल्यूएशन सर्व करें।
- अपडेट्स के लिए एक स्ट्रीम खुली रखें और रिपेयर पाथ के रूप में पोल करें।
सक्रिय रूलसेट को कभी भी सीधे (in place) म्यूटेट न करें। एक नया इम्यूटैबल स्नैपशॉट बनाएं और एक संदर्भ की अदला-बदली करें ताकि समवर्ती (concurrent) रिक्वेस्ट्स या तो पूरा पुराना वर्ज़न देखें या पूरा नया वर्ज़न देखें। डायग्नोस्टिक डिटेल्स में लागू वर्ज़न और इवैल्यूएशन का कारण रिकॉर्ड करें।
स्टेप 6: हैप्पी पाथ से पहले फ़ेल्योर सिमेंटिक्स डिज़ाइन करें
| विफलता (Failure) | इवैल्यूएशन व्यवहार | रिकवरी |
|---|---|---|
| कंट्रोल API या डेटाबेस अनुपलब्ध | stale_after तक अंतिम मान्य स्नैपशॉट का उपयोग करें, फिर फ़्लैग के स्टेल एक्शन का पालन करें | एडिट्स को ब्लॉक करें, कंट्रोल प्लेन को पुनर्स्थापित करें, केवल वैलिडेशन के बाद नया वर्ज़न पब्लिश करें |
| स्ट्रीम डिस्कनेक्ट हो गई | स्थानीय स्थिति का उपयोग करें और अपडेट स्थिति को स्टेल चिह्नित करें | जिटर के साथ पुनः कनेक्ट करें; एक अंतराल के बाद पोल करें और पूर्ण स्नैपशॉट का अनुरोध करें |
| SDK बिना किसी स्नैपशॉट के प्रारंभ होता है | टाइप्ड कोड फ़ॉलबैक लौटाएं | असंबद्ध एप्लिकेशन स्टार्टअप को हमेशा के लिए ब्लॉक किए बिना बूटस्ट्रैप का पुनः प्रयास करें |
| अमान्य या आउट-ऑफ़-ऑर्डर पैच | वर्तमान वर्ज़न बनाए रखें | इसे अस्वीकार करें, एक अलर्ट भेजें, विहित (canonical) स्नैपशॉट प्राप्त करें |
| खराब नियम पब्लिश हुआ | मौजूदा इवैल्यूएशन आंतरिक रूप से सुसंगत है लेकिन गलत है | रोलआउट रोकें, पिछले ज्ञात-अच्छे डेफ़िनिशन को एक नए ऑडिट किए गए वर्ज़न के रूप में पब्लिश करें |
| रीजनल रिले अनुपलब्ध | स्थानीय रूप से जारी रखें और किसी अन्य रिले या पोलिंग एंडपॉइंट का प्रयास करें | पुनः कनेक्ट ट्रैफ़िक को सीमित करें और एक सिंक्रोनाइज़्ड बूटस्ट्रैप स्टॉर्म से बचें |
इमरजेंसी ऑफ़ स्विच एक प्राथमिकता वाली लेन (priority lane) के साथ उसी टिकाऊ पब्लिश पाथ का उपयोग करता है, न कि किसी गैर-ऑडिट किए गए म्यूटैबल साइड चैनल का। यह केवल पूर्व-अधिकृत ब्रेक-ग्लास नीति के तहत अनुमोदन के लिए सामान्य प्रतीक्षा को छोड़ सकता है, लेकिन फिर भी एक्टर, कारण, पिछले वर्ज़न और परिणाम को रिकॉर्ड करता है। पाँच-सेकंड का प्रोपेगेशन लक्ष्य यह गारंटी नहीं दे सकता कि प्रत्येक डिस्कनेक्ट किया गया इंस्टेंस स्विच हो गया है; विनाशकारी कार्रवाइयों के लिए स्वतंत्र प्रवर्तन की आवश्यकता होती है।
स्टेप 7: प्लेटफ़ॉर्म को कॉन्फ़िगरेशन द्वारा अथॉरिटी बनने से बचाएं
टेनेंट, प्रोजेक्ट और एनवायरनमेंट द्वारा मैनेजमेंट रोल्स को अलग करें। प्रोडक्शन एडिट्स के लिए दूसरे अप्रूवर की आवश्यकता हो सकती है, जबकि डेवलपमेंट एडिट्स सीधे पब्लिश हो सकते हैं। क्रेडेंशियल्स को एन्क्रिप्ट करें, SDK कीज़ को रोटेट करें, मैनेजमेंट कॉल्स को रेट-लिमिट करें, और सुनिश्चित करें कि एक सर्वर की फ़्लैग्स को एडिट नहीं कर सकती है। एक अपेंड-ओनली ऑडिट लॉग और इम्यूटैबल आर्टिफ़ैक्ट्स घटना पुनर्निर्माण (incident reconstruction) को संभव बनाते हैं।
क्लाइंट डिलीवरी को सर्वर डिलीवरी से अलग समझें। ब्राउज़रों या मोबाइल डिवाइसेस को केवल वे फ़्लैग्स भेजें जो क्लाइंट एक्सपोज़र के लिए स्पष्ट रूप से स्वीकृत हैं, और अधिमानतः उनके संदर्भ के लिए पहले से मूल्यांकित मान भेजें। एक यूज़र क्लाइंट स्थिति का निरीक्षण या परिवर्तन कर सकता है, इसलिए एक फ़्लैग प्रेजेंटेशन को बदल सकता है लेकिन ऑथराइज़ेशन प्रदान नहीं कर सकता, भुगतान को बायपास नहीं कर सकता, या सर्वर-साइड पात्रता जांच को प्रतिस्थापित नहीं कर सकता। इवैल्यूएशन संदर्भ में व्यक्तिगत रूप से पहचान योग्य फ़ील्ड्स को न्यूनतम करें और टेलीमेट्री पहचानकर्ताओं को स्यूडोनिमाइज़ करें।
प्रत्येक अस्थायी रिलीज़ फ़्लैग को एक ओनर और रिटायरमेंट की शर्त दें। रोलआउट पूरा होने के बाद, पहले जीतने वाले पाथ को स्थायी बनाएं, फिर फ़्लैग का मूल्यांकन करना बंद करें, फिर कोड संदर्भ समाप्त होने के बाद डेफ़िनिशन को हटा दें। अन्यथा पुरानी ब्रांचेस और इंटरैक्ट करने वाले फ़्लैग्स परीक्षण मैट्रिक्स को अनिश्चित काल तक विस्तारित करते हैं।
स्टेप 8: क्षमता की दोबारा जांच करें और डिज़ाइन को सिद्ध करें
औसतन 2 KB के 500 सब्सक्राइब किए गए फ़्लैग्स पर, एक रनटाइम स्नैपशॉट लगभग 1 MB का होता है। एक साथ 20,000 इंस्टेंसेस को बूटस्ट्रैप करने से प्रोटोकॉल और रेप्लिकेशन ओवरहेड से पहले लगभग 20 GB ट्रांसफर होता है। रीजनल रिले या ऑब्जेक्ट डिलीवरी के पीछे विहित आर्टिफ़ैक्ट्स रखें, कंडीशनल वर्ज़न्स का उपयोग करें, पुनः कनेक्ट को जिटर करें, और बूटस्ट्रैप कंकरेंसी को सीमित करें। 20,000 इंस्टेंसेस पर भेजा गया एक एकल 2 KB बदलाव लगभग 40 MB का लॉजिकल पेलोड है, इसलिए पूर्ण रीफ्रेश की तुलना में इंक्रीमेंटल डिलीवरी बहुत सस्ती है।
प्रति सेकंड पचास लाख इवैल्यूएशन को सिंक्रोनस रूप से पचास लाख नेटवर्क इवेंट्स उत्सर्जित नहीं करने चाहिए। एक 200-बाइट का इवेंट भी रेप्लिकेशन से पहले लगभग 1 GB प्रति सेकंड, या 86.4 TB प्रति दिन होगा। सामान्य डायग्नोस्टिक्स को बफ़र, बैच, सैंपल या एग्रीगेट करें। संपूर्ण असाइनमेंट इवेंट्स को केवल तभी सुरक्षित रखें जब किसी एक्सपेरिमेंट कॉन्ट्रैक्ट को उनकी आवश्यकता हो, और टेलीमेट्री को एक बाउंडेड कतार पर रखें जो इवैल्यूएशन में देरी किए बिना गैर-महत्वपूर्ण इवेंट्स को छोड़ सकती है।
वैलिडेशन थ्रूपुट से अधिक को कवर करता है:
- प्रत्येक SDK कार्यान्वयन के विरुद्ध समान गोल्डन रूल्स और संदर्भ चलाएं और मान, वैरिएंट, कारण और त्रुटि व्यवहार की तुलना करें।
- बकेट डिटर्मिनिज्म, अनुमानित वितरण और स्थिरता का प्रॉपर्टी-परीक्षण करें जब एक मौजूदा रोलआउट रेंज का विस्तार होता है।
- नियम संख्या और सेगमेंट आकार के अनुसार स्थानीय p50 और p99 को मापें; पब्लिश-टू-अप्लाई अंतराल को अलग से मापें।
- स्ट्रीम्स को डिस्कनेक्ट करें, कंट्रोल डेटाबेस को रोकें, एक पैच को दूषित करें, एक वर्ज़न छोड़ें, क्रेडेंशियल्स को समाप्त करें, और सभी इंस्टेंसेस को एक साथ रीस्टार्ट करें।
- एक छोटे कैनरी कोहोर्ट में एक खराब नियम पब्लिश करें, एक हेल्थ अलार्म चालू करें, और सत्यापित करें कि रोलबैक एक नया ऑडिट किया गया वर्ज़न बनाता है और प्रोपेगेट करता है।
- टेनेंट आइसोलेशन, प्रोडक्शन अप्रूवल, क्लाइंट एक्सपोज़र फ़िल्टरिंग, ऑडिट पूर्णता, और फ़्लैग रिटायरमेंट को सत्यापित करें।
एक मजबूत उत्तर का उदाहरण
"मैं बेस सिस्टम को सर्वर-साइड इवैल्यूएशन तक सीमित रखूँगा। तीन क्षेत्रों में 20,000 इंस्टेंसेस हैं, लेकिन प्रति सेकंड केवल 100 कंट्रोल राइट्स हैं, इसलिए दोनों ट्रैफ़िक पाथ्स को उपलब्धता निर्भरता साझा नहीं करनी चाहिए। मैनेजमेंट सर्विस ड्राफ़्ट्स और इम्यूटैबल पब्लिश किए गए वर्ज़न्स को एक रिलेशनल डेटाबेस में स्टोर करती है। प्रत्येक पब्लिश प्रकारों, नियम संदर्भों और अनुमतियों को मान्य करता है, अपेक्षित पूर्व वर्ज़न की जांच करता है, एक ऑडिट रिकॉर्ड और आउटबॉक्स प्रविष्टि लिखता है, फिर एक विहित प्रोजेक्ट-एंड-एनवायरनमेंट आर्टिफ़ैक्ट बनाता है।
रीजनल रिले उस आर्टिफ़ैक्ट को वितरित करते हैं। प्रत्येक SDK एक लास्ट-नोन-गुड स्नैपशॉट लोड करता है, एक स्ट्रीम पर अपडेट प्राप्त करता है, और अंतराल की मरम्मत के लिए पोल करता है। यह एक नए इम्यूटैबल स्नैपशॉट को परमाणु रूप से स्थापित करता है और स्थानीय रूप से मूल्यांकन करता है, जिससे कंट्रोल प्लेन बंद होने पर भी रिक्वेस्ट लेटेंसी 1-मिलीसेकंड p99 लक्ष्य से नीचे रहती है। लास्ट-नोन-गुड कम से कम 15 मिनट के लिए मान्य है; पब्लिश की गई स्टेल सीमा के बाद, फ़्लैग या तो उस मान को रखता है या अपनी जोखिम नीति के अनुसार टाइप्ड कोड फ़ॉलबैक का उपयोग करता है। स्थानीय वर्ज़न, ताज़गी (freshness), और इवैल्यूएशन कारण अवलोकनीय (observable) हैं।
इवैल्यूएशन क्रम ऑफ़ स्टेट, स्पष्ट टारगेट्स, ऑर्डर्ड रूल्स, वेटेड परिणाम, फिर डिफ़ॉल्ट है। पर्सेंटेज रोलआउट टेनेंट, एनवायरनमेंट, फ़्लैग, सॉल्ट और एक स्थिर टारगेटिंग की को 100,000 बकेट्स में हैश करता है, इसलिए प्रत्येक इंस्टेंस समान विकल्प चुनता है। हैश इनपुट्स को बदलना एक माइग्रेशन है; एक कोहोर्ट की आवश्यकता वाले कई फ़्लैग्स संयोगवश बराबर प्रतिशत के बजाय एक साझा सेगमेंट का उपयोग करते हैं।
सबसे बड़ा बर्स्ट फ्लीट बूटस्ट्रैप है: 1 MB का स्कोप्ड स्नैपशॉट 20,000 इंस्टेंसेस से गुणा करने पर लगभग 20 GB होता है। मैं स्नैपशॉट्स को रीजनल रूप से सर्व करूँगा, डेल्टास भेजूंगा, पुनः कनेक्ट्स को जिटर करूँगा, और पुनः प्रयासों को सीमित करूँगा। इवैल्यूएशन टेलीमेट्री को बैच और सैंपल किया जाता है क्योंकि प्रति सेकंड 5 मिलियन सिंक्रोनस इवेंट्स को रिकॉर्ड करना प्रोडक्ट पाथ को खतरे में डाल देगा। अंत में, मैं क्रॉस-SDK अनुरूपता, प्रोपेगेशन p99, रीस्टार्ट स्टॉर्म्स, स्टेल ऑपरेशन, दूषित और लापता वर्ज़न्स, कैनरी रोलबैक, ब्रेक-ग्लास ऑडिट, टेनेंट आइसोलेशन और क्लाइंट एक्सपोज़र का परीक्षण करूँगा। सिस्टम तब सफल होता है जब रिक्वेस्ट इवैल्यूएशन स्थानीय और डिटर्मिनिस्टिक रहता है जबकि हर कॉन्फ़िगरेशन परिवर्तन गवर्न और रिकवरेबल रहता है।"
सामान्य गलतियां
- प्रत्येक इवैल्यूएशन के लिए एक केंद्रीय सेवा को कॉल करना → प्रोडक्ट लेटेंसी और उपलब्धता अब फ़्लैग सर्विस पर निर्भर करती है → सर्वर SDKs को वर्ज़न किए गए नियम भेजें और प्रोसेस में मूल्यांकन करें।
- प्रत्येक रिक्वेस्ट पर उपयोगकर्ताओं को अनियमित रूप से चुनना → एक यूज़र वेरिएंट्स के बीच चलता है और एक्सपेरिमेंट डेटा दूषित हो जाता है → दस्तावेज़बद्ध फ़्लैग-विशिष्ट इनपुट्स के साथ एक स्थिर टारगेटिंग की को हैश करें।
- लास्ट-नोन-गुड को स्थायी रूप से सही मानना → एक डिस्कनेक्ट किया गया इंस्टेंस अनिश्चित काल तक एक असुरक्षित बासी नियम की सेवा कर सकता है → स्टेलनेस ऑब्जर्वेबिलिटी, पुनः कनेक्ट और मरम्मत व्यवहार, और एक एप्लिकेशन सुरक्षा फ़ॉलबैक को परिभाषित करें।
- सर्वर रूलसेट को ब्राउज़र पर भेजना → यूज़र्स संवेदनशील सेगमेंट्स और क्रेडेंशियल्स का निरीक्षण कर सकते हैं → क्लाइंट-सुरक्षित फ़्लैग्स को फ़िल्टर करें या दूरस्थ रूप से मूल्यांकन करें, और सर्वर पर ऑथराइज़ेशन लागू करें।
- एक साझा नियम ऑब्जेक्ट को सीधे (in place) अपडेट करना → समवर्ती रिक्वेस्ट्स आंशिक रूप से लागू कॉन्फ़िगरेशन का निरीक्षण कर सकते हैं → एक पूर्ण इम्यूटैबल स्नैपशॉट को मान्य करें और संदर्भों को परमाणु रूप से स्वैप करें।
- प्रत्येक इवैल्यूएशन को सिंक्रोनस रूप से लॉग करना → टेलीमेट्री रिक्वेस्ट पाथ में सबसे अधिक मात्रा वाली निर्भरता बन जाती है → गैर-महत्वपूर्ण इवेंट्स को बैच, सैंपल, एग्रीगेट और शेड करें।
- आपातकालीन परिवर्तनों को गैर-ऑडिटेड बनाना → सबसे तेज़ रिकवरी पाथ एक ट्रेस न करने योग्य प्रोडक्शन बैकडोर बन जाता है → पूर्व-अधिकृत ब्रेक-ग्लास नीति और इम्यूटैबल ऑडिट के साथ प्राथमिकता पब्लिश लेन का उपयोग करें।
- फ़्लैग्स को कभी रिटायर न करना → अप्रचलित ब्रांचेस और फ़्लैग इंटरैक्शन्स परीक्षण लागत को कई गुना बढ़ा देते हैं → एक ओनर असाइन करें और जीतने वाले कोड पाथ के स्थायी होने के बाद डेफ़िनिशन को हटा दें।
फ़ॉलो-अप प्रश्न और उत्तर
फ़ॉलो-अप 1: आप ब्राउज़र और मोबाइल SDKs का समर्थन कैसे करेंगे?
पूरा सर्वर रूलसेट डिलीवर न करें। चिह्नित करें कि कौन से फ़्लैग्स क्लाइंट-एक्सपोज़ेबल हैं, एप्लिकेशन को मैनेजमेंट क्रेडेंशियल के साथ भरोसा करने के बजाय उसे प्रमाणित करें, और फ़िल्टर किए गए मान या संदर्भ-विशिष्ट मूल्यांकित परिणाम लौटाएं। एक दृश्यमान वर्ज़न और फ्रेशनेस स्थिति के साथ ऑफ़लाइन उपयोग के लिए मानों को कैश करें। एक क्लाइंट फ़्लैग एक उपयोगकर्ता-अनुभव संकेत बना रहता है; सर्वर स्वतंत्र रूप से अनुमतियों, खरीदारी, कोटा और अन्य सुरक्षा निर्णयों की जांच करता है।
फ़ॉलो-अप 2: कई फ़्लैग्स बिल्कुल समान रोलआउट कोहोर्ट कैसे रखते हैं?
समान प्रतिशत अपर्याप्त हैं जब प्रत्येक फ़्लैग की हैश इनपुट को बदल देती है। एक सामान्य एक्सपेरिमेंट ID द्वारा कीड (keyed) एक साझा, वर्ज़न किया गया सेगमेंट या एक एक्सपेरिमेंट असाइनमेंट बनाएं, फिर प्रत्येक फ़्लैग से उसका संदर्भ लें। सेगमेंट और निर्भर फ़्लैग वर्ज़न्स को लगातार पब्लिश करें, और एक्सपोज़र बढ़ाने से पहले परीक्षण करें कि कोहोर्ट सदस्यता स्थिर रहे।
फ़ॉलो-अप 3: क्या होगा यदि किसी सेगमेंट में एक करोड़ (ten million) सदस्य हों?
प्रत्येक स्नैपशॉट में पूरी सदस्य सूची को एम्बेड न करें। सदस्यता को एक संक्षिप्त वर्ज़न वाले आर्टिफ़ैक्ट के रूप में प्रस्तुत करें, इसे सब्जेक्ट हैश द्वारा शार्ड करें, या एक एट्रिब्यूट की पूर्व-गणना करें जिसे इवैल्यूएटर उपभोग कर सके। ब्लूम फ़िल्टर नकारात्मक लुकअप ट्रैफ़िक को कम कर सकते हैं लेकिन एकमात्र ऑथराइज़ेशन तंत्र नहीं हो सकते क्योंकि गलत सकारात्मक (false positives) मौजूद होते हैं। मेमोरी, लुकअप लेटेंसी, अपडेट प्रवर्धन (amplification), और बासी सदस्यता को सामान्य नियमों से अलग मापें।
फ़ॉलो-अप 4: क्या एक इमरजेंसी ऑफ़ स्विच तात्कालिक हो सकता है?
कोई भी वितरित पब्लिश डिस्कनेक्ट की गई प्रक्रियाओं तक तुरंत नहीं पहुंचता है। आपातकालीन परिवर्तनों को प्राथमिकता दें, रीजनल स्ट्रीम्स को चालू रखें, स्वीकृतियों (acknowledgments) को मापें, और लैगिंग वर्ज़न्स पर अलर्ट करें। विनाशकारी ऑपरेशन के लिए, फ़्लैग को सर्वर-लागू गार्ड के साथ संयोजित करें जैसे कि राइट एंडपॉइंट को डिसेबल करना, किसी क्षमता को रद्द करना, या गेटवे पर कार्य को ब्लॉक करना। फ़्लैग रिकवरी की गति में सुधार करता है लेकिन एक कठिन सुरक्षा सीमा को प्रतिस्थापित नहीं करता है।
फ़ॉलो-अप 5: आप हैशिंग एल्गोरिदम को कैसे माइग्रेट करेंगे?
प्रत्येक पब्लिश किए गए फ़्लैग के साथ एक एल्गोरिदम वर्ज़न और सॉल्ट स्टोर करें। पुराने और नए इवैल्यूएटर्स को शैडो मोड में चलाएं और असाइनमेंट मूवमेंट को मापें। यदि हलचल स्वीकार्य है, तो एक स्टेज्ड माइग्रेशन पब्लिश करें; यदि नहीं, तो रोलआउट पूरा होने तक मौजूदा सब्जेक्ट असाइनमेंट्स को एक सेगमेंट या माइग्रेशन टेबल में सुरक्षित रखें। SDK हैश कार्यान्वयन को कभी भी चुपचाप न बदलें क्योंकि विभिन्न वर्ज़न्स असहमत होंगे।
फ़ॉलो-अप 6: आप फ़्लैग डिपेंडेंसी चक्र को कैसे रोकते हैं?
पब्लिश के दौरान पूर्वापेक्षा ग्राफ़ बनाएं और जब डेप्थ-फ़र्स्ट ट्रैवर्सल को कोई चक्र मिले तो किसी वर्ज़न को अस्वीकार करें। अधिकतम पूर्वापेक्षा गहराई और कुल इवैल्यूएशन कार्य को सीमित करें ताकि एक एसाइक्लिक लेकिन पैथोलॉजिकल ग्राफ़ लेटेंसी का उल्लंघन न कर सके। आर्टिफ़ैक्ट में संदर्भित फ़्लैग वर्ज़न्स को शामिल करें, SDKs में इवैल्यूएशन क्रम का परीक्षण करें, और डायग्नोस्टिक विवरणों में डिपेंडेंसी श्रृंखला को सामने लाएं।