प्रॉम्प्ट और लागू संदर्भ
मल्टी-टेनेंट API प्लेटफ़ॉर्म के लिए एक रेट लिमिटर डिज़ाइन करें: मुफ़्त टेनेंट्स को प्रति मिनट 100 अनुरोध मिलते हैं, पेड टेनेंट्स को 10,000 मिलते हैं, और प्लेटफ़ॉर्म कई एप्लिकेशन इंस्टेंसेस और क्षेत्रों में चलता है। एल्गोरिदम की तुलना करें और शेयर्ड स्टेट, 429 प्रतिक्रियाओं, विफलता डिग्रेडेशन और सत्यापन की व्याख्या करें।
यह बैकएंड, प्लेटफ़ॉर्म और सिस्टम डिज़ाइन इंटरव्यू के लिए उपयुक्त है। एक सार्वजनिक साक्षात्कार रिकॉर्ड समय-आधारित रीफ़िल के साथ प्रति-उपयोगकर्ता टोकन-बकेट कोडिंग समस्या प्रस्तुत करता है; सिस्टम-डिज़ाइन सामग्री रेट लिमिटिंग को एक मानक मल्टी-टेनेंट API चर्चा के रूप में मानती है। मुख्य कौशल शेयर्ड स्टेट, टेनेंट नीति और ट्रैफ़िक सुरक्षा है—किसी एक क्लाउड प्रदाता की सेटिंग्स को याद रखना नहीं।
साक्षात्कारकर्ता क्या मूल्यांकन करता है
- क्या आप औसत दर, बर्स्ट क्षमता, टेनेंट निष्पक्षता और वैश्विक सुरक्षा को अलग-अलग समझते हैं।
- क्या आप टोकन बकेट, फिक्स्ड विंडो और स्लाइडिंग विंडो की सीमाओं और लागतों की व्याख्या कर सकते हैं।
- क्या हॉट कीज़, पार्टिशन और क्लॉक्स को संबोधित करते हुए इंस्टेंसेस के बीच शेयर्ड स्टेट को एटॉमिक रूप से अपडेट किया जाता है।
- क्या 429 प्रतिक्रियाएं, पुनः प्रयास (retry) संकेत, डिग्रेडेशन और टेलीमेट्री लिमिटर को सिंगल पॉइंट ऑफ़ फेलियर बनने से रोकते हैं।
उत्तर देने से पहले स्पष्ट करने वाले प्रश्न
- क्या विषय एक API की, टेनेंट, उपयोगकर्ता, IP या इनका संयोजन है? अनाम अनुरोधों को कैसे समूहीकृत किया जाता है?
- क्या नीति एक औसत दर, एक सख्त स्लाइडिंग विंडो, या नियंत्रित बर्स्ट है? क्या कोई दैनिक कोटा भी है?
- क्या मल्टी-रीजन के लिए सटीक वैश्विक प्रवर्तन (global enforcement) की आवश्यकता है, या थोड़ा सा ओवररन उपलब्धता बनाए रख सकता है?
- क्या अस्वीकृत अनुरोधों को तत्काल 429 प्राप्त होना चाहिए या एक बाउंडेड कतार में प्रवेश करना चाहिए? क्या निर्भरता (dependency) बर्स्ट को बिल्कुल भी सहन कर सकती है?
30-सेकंड का उत्तर ढांचा
मैं गेटवे पर सामान्य IP और अप्रमाणित सुरक्षा रखूँगा, फिर एप्लिकेशन लेयर में टेनेंट-जागरूक नीति लागू करूँगा। यदि API छोटे बर्स्ट को सहन करता है, तो मैं टोकन बकेट से शुरुआत करूँगा। प्रत्येक टेनेंट बकेट टोकन और अंतिम रीफ़िल समय को एटॉमिक रूप से शेयर्ड स्टेट में संग्रहीत करता है। सीमा से अधिक अनुरोधों को एक गणना योग्य रीट्राय संकेत के साथ 429 प्राप्त होता है। यदि सटीक वैश्विक गणना की आवश्यकता नहीं है, तो क्षेत्रीय कोटा और वैश्विक ओवररन निगरानी विलंबता (latency) के बदले थोड़ी सटीकता का समझौता करते हैं; स्टोरेज विफलताओं में अलर्ट के साथ एक स्पष्ट fail-open या fail-closed नीति का उपयोग किया जाता है।
चरण-दर-चरण गहन विश्लेषण
बजट और निष्पक्षता को परिभाषित करें
प्रति मिनट सौ अनुरोध मुफ़्त टेनेंट का दीर्घकालिक बजट है, और 10,000 पेड टेनेंट का है। दोनों को एक स्वतंत्र बर्स्ट क्षमता की भी आवश्यकता है; एक एकल वैश्विक काउंटर किसी भी नीति को व्यक्त नहीं कर सकता है। एक वैश्विक गार्ड को कुल RPS को सीमित करना चाहिए ताकि एक बड़ा टेनेंट डेटाबेस कनेक्शन समाप्त न कर सके। एक नीति कुंजी में टेनेंट ID, API क्रिया और नीति संस्करण शामिल होना चाहिए ताकि असंबंधित एंडपॉइंट गलती से भत्ता (allowance) साझा न करें।
एल्गोरिदम चुनें
| एल्गोरिदम | मुख्य सिमेंटिक्स | लागत और जोखिम | उपयुक्तता |
|---|---|---|---|
| Token bucket | नियंत्रित बर्स्ट के साथ बाउंडेड औसत दर | दो स्थिति मान; रीफ़िल और उपभोग एटॉमिक होना चाहिए | उपयोगकर्ता-सामना करने वाले API जो छोटे बर्स्ट को सहन करते हैं |
| Fixed window | निश्चित अवधियों में अनुरोधों की गणना | विंडो सीमा कॉन्फ़िगर की गई दर से दोगुनी तक पहुंच सकती है | सरल नियम जहां सन्निकटन (approximation) स्वीकार्य है |
| Sliding window log | सक्रिय विंडो में सटीक गणना | टाइमस्टैम्प संग्रहीत करता है; मेमोरी और क्लीनअप महंगे हैं | सख्त सटीकता की आवश्यकता वाली छोटी आबादी |
| Sliding window counter | आसन्न विंडो से भारित अनुमान | अनुमानित लेकिन मेमोरी कुशल; त्रुटि का उल्लेख किया जाना चाहिए | बड़े पैमाने पर निष्पक्षता सीमाएं |
AWS API Gateway टोकन-बकेट थ्रॉटलिंग का दस्तावेजीकरण करता है: टोकन दर स्थिर-अवस्था ट्रैफ़िक को व्यक्त करती है और बर्स्ट बकेट क्षमता को व्यक्त करता है। यह 429 वापस कर सकता है, लेकिन सीमाएं एक पूर्ण गणितीय सीमा के बजाय सर्वोत्तम-प्रयास लक्ष्य हैं। नीति के इरादे को प्लेटफ़ॉर्म की गारंटी से अलग रखें।
टोकन-बकेट इनवेरिएंट
टोकन गणना हमेशा [0, capacity] में रहती है। आने पर, बीता हुआ समय गुणा रीफ़िल दर द्वारा रीफ़िल करें, क्षमता पर सीमित करें, और फिर कम से कम एक टोकन की जांच करें; एक अनुमत अनुरोध एक टोकन का उपभोग करता है। इस क्रम का अर्थ है कि एक निष्क्रिय अवधि केवल बर्स्ट सीमा तक जमा होती है, न कि डाउनटाइम के बाद असीमित क्रेडिट बनाती है।
~~~text allow(key, now): state = atomicRead(key) elapsed = max(0, now - state.lastRefill) refilled = min(capacity, state.tokens + elapsed * rate) if refilled < 1: atomicWrite(key, refilled, now) return reject(429) atomicWrite(key, refilled - 1, now) return allow ~~~
उत्पादन में, स्यूडोकोड को एक Lua स्क्रिप्ट, लेनदेन, या समकक्ष तुलना-और-स्वैप (compare-and-swap) ऑपरेशन के रूप में चलना चाहिए। दो स्वतंत्र रीड और राइट कॉल कॉनकरेंसी के तहत टोकन को ओवरसेल कर सकते हैं। टाइमस्टैम्प एक विश्वसनीय मोनोटोनिक स्रोत से आने चाहिए; क्लाइंट्स को उन्हें सबमिट नहीं करना चाहिए।
प्लेसमेंट और शेयर्ड स्टेट
गेटवे स्पष्ट IP फ़्लड और अप्रमाणित वॉल्यूम को रोकता है; एप्लिकेशन लेयर टेनेंट, उपयोगकर्ता या एंडपॉइंट नीति लागू करती है। यदि प्रत्येक इंस्टेंस केवल स्थानीय मेमोरी में गणना करता है, तो लोड बैलेंसिंग एक टेनेंट को इंस्टेंसेस में कॉल वितरित करने और कई भत्ते प्राप्त करने की अनुमति देता है। शेयर्ड Redis, एक एटॉमिक की-वैल्यू स्टोर, या एक सशर्त रूप से लिखा गया डेटाबेस स्थिति रख सकता है; चुनाव विलंबता, सटीकता और विफलता मॉडल पर निर्भर करता है।
मल्टी-रीजन विकल्प स्पष्ट हैं: एक वैश्विक स्टोर क्रॉस-रीजन विलंबता पर अधिक सटीक भत्ता देता है; स्वतंत्र क्षेत्रीय बकेट तेज़ हैं लेकिन संक्षेप में ओवररन कर सकते हैं; क्षेत्रीय आवंटन और एक वैश्विक गार्ड उनके बीच बैठते हैं। वैश्विक सख्त सीमा का दावा करने से पहले पूछें कि क्या सटीकता उपलब्धता से अधिक मायने रखती है।
अस्वीकृति, डिग्रेडेशन और टेलीमेट्री
Retry-After या शेष-कोटा हेडर के साथ 429 लौटाएं। क्लाइंट्स को तुरंत फ़ीडबैक लूप में पुनः प्रयास करने के बजाय बाउंडेड बैकऑफ़ का उपयोग करना चाहिए। यदि लिमिटर स्टोरेज विफल हो जाता है, तो उच्च जोखिम वाले राइट्स आमतौर पर fail closed होते हैं या एक बाउंडेड कतार में प्रवेश करते हैं; कम जोखिम वाले रीड संक्षेप में fail open हो सकते हैं, लेकिन उन्हें एक स्थानीय सर्किट ब्रेकर, समाप्ति और कुल सीमा की आवश्यकता होती है। अनुमति और अस्वीकार दरों, प्रति-टेनेंट कोटा हिट, स्टोरेज विलंबता, हॉट कीज़, स्क्रिप्ट त्रुटियों और वास्तविक डाउनस्ट्रीम लोड की अलग से निगरानी करें।
उच्च गुणवत्ता वाला नमूना उत्तर
मैं दो परतों का उपयोग करूँगा: गेटवे IP और अप्रमाणित फ़्लड से बचाता है, जबकि एप्लिकेशन टेनेंट और एंडपॉइंट नीति लागू करता है। मुफ़्त और सशुल्क टेनेंट्स के पास अलग-अलग दर और बर्स्ट मान होते हैं। मैं डिफ़ॉल्ट रूप से एक टोकन बकेट का उपयोग करूँगा क्योंकि एक API आमतौर पर दीर्घकालिक औसत को लागू करते हुए एक छोटे बर्स्ट को सहन कर सकता है। प्रत्येक बकेट टोकन और उसके अंतिम रीफ़िल समय को संग्रहीत करता है, और एक एटॉमिक स्क्रिप्ट शेयर्ड स्टोरेज में रीफ़िल, जांच और उपभोग करती है।
यदि क्षेत्रों को प्रत्येक अनुरोध के लिए एक सटीक वैश्विक परिणाम की आवश्यकता नहीं है, तो मैं क्षेत्रीय कोटा आवंटित करूँगा और असामान्य ओवररन का पता लगाने के लिए वैश्विक टेलीमेट्री का उपयोग करूँगा। यदि भुगतान या कोटा निपटान सख्त होना चाहिए, तो मैं एक मजबूत-कंसिस्टेंसी निर्णय बिंदु का उपयोग करूँगा और विलंबता को स्वीकार करूँगा। सीमा से अधिक अनुरोधों को 429 और पुनः प्रयास मार्गदर्शन प्राप्त होता है; स्टोरेज विफलता एंडपॉइंट जोखिम के आधार पर fail closed, शॉर्ट fail open, या बाउंडेड कतार चुनती है। फिर मैं बर्स्ट क्षमता, विंडो सीमाओं, टेनेंट निष्पक्षता, विफलता पुनर्प्राप्ति, और डाउनस्ट्रीम लोड का लोड-परीक्षण करूँगा—केवल 429 की संख्या का नहीं।
सामान्य गलतियाँ
- "Redis काउंटरों का उपयोग करें" → कोई नीति सिमेंटिक्स या एटॉमीसिटी नहीं → बकेट स्थिति, स्क्रिप्ट सीमाओं और विफलता व्यवहार को निर्दिष्ट करें।
- प्रत्येक टेनेंट के लिए एक कोटा → एक बड़ा टेनेंट छोटे टेनेंट्स को भूखा मारता है → टेनेंट और एंडपॉइंट द्वारा नीति को विभाजित करें, फिर एक वैश्विक गार्ड जोड़ें।
- फिक्स्ड विंडो को एक सख्त प्रति-मिनट छत के रूप में मानना → सीमा ट्रैफ़िक दर के दोगुने तक पहुंच सकता है → त्रुटि का उल्लेख करें और आवश्यकता पड़ने पर स्लाइडिंग या टोकन बकेट चुनें।
- लिमिटर स्टोरेज विफल होने पर पूरी छूट देना → निर्भरता पहले क्रैश हो जाती है → व्यावसायिक जोखिम द्वारा बाउंडेड डिग्रेडेशन चुनें और उस पर अलर्ट करें।
- क्लाइंट्स को 429 का तुरंत पुनः प्रयास करने के लिए कहना → अस्वीकृत ट्रैफ़िक अधिक लोड बन जाता है → पुनः प्रयास मार्गदर्शन, जिटर (jitter), और एक सीमा प्रदान करें।
फॉलो-अप प्रश्न और प्रतिक्रियाएं
आप एक टेनेंट को 20 इंस्टेंसेस में भत्ते को गुणा करने से कैसे रोकते हैं?
बकेट की स्थिति को प्रत्येक इंस्टेंस के लिए दृश्यमान शेयर्ड स्टोरेज में रखें और इसे टेनेंट नीति कुंजी के तहत एटॉमिक रूप से अपडेट करें। यदि केवल स्थानीय काउंटर उपलब्ध हैं, तो परिणाम को अनुमानित कहें और गेटवे-व्यापी सीमा जोड़ें; वैश्विक सटीकता का दावा न करें।
क्या होगा यदि 100 अनुरोध प्रति मिनट को सभी क्षेत्रों में सख्ती से लागू किया जाना चाहिए?
एक मजबूत-कंसिस्टेंसी वैश्विक निर्णय बिंदु का उपयोग करें या टेनेंट के गृह क्षेत्र के माध्यम से कटौती को क्रमबद्ध (serialize) करें। इसकी लागत क्रॉस-रीजन विलंबता और क्षेत्रीय विफलता के दौरान कम उपलब्धता है। यदि एक छोटा ओवररन स्वीकार्य है, तो क्षेत्रीय कोटा प्लस सुलह (reconciliation) का उपयोग करें और त्रुटि को SLO में लिखें।
आप धीमे लिमिटर को API को धीमा करने से कैसे रोकते हैं?
लिमिटर कॉल के चारों ओर सख्त टाइमआउट और सर्किट ब्रेकर सेट करें। स्टोरेज आउटेज के लिए एक स्थानीय सुरक्षा सीमा रखें और एंडपॉइंट जोखिम के आधार पर डिग्रेड करें। व्यावसायिक सफलता दर से स्वतंत्र रूप से लिमिटर विलंबता, टाइमआउट और स्क्रिप्ट विफलताओं को ट्रैक करें।
429 लौटाने के बजाय आपको कब कतारबद्ध (queue) करना चाहिए?
केवल तभी कतारबद्ध करें जब काम एसिंक्रोनस हो, प्रतीक्षा समय उपयोगकर्ता के बजट में फिट बैठता हो, और निर्भरता को स्मूथिंग की आवश्यकता हो। कतार बाउंडेड होनी चाहिए और पूर्ण होने पर अस्वीकार करनी चाहिए। इंटरैक्टिव रीड्स या अनबाउंडेड प्रतीक्षाओं को आमतौर पर ईमानदारी से 429 वापस करना चाहिए।
आप फिक्स्ड-विंडो सीमा खामी का परीक्षण कैसे करते हैं?
विंडो समाप्त होने से ठीक पहले एक बर्स्ट भेजें और इसके शुरू होने के ठीक बाद दूसरा, फिर प्रत्येक रोलिंग अंतराल में अनुरोधों की गणना करें। टोकन-बकेट निष्क्रिय रीफ़िल, पूर्ण-बकेट बर्स्ट, और नियंत्रित क्लॉक का उपयोग करके समवर्ती उपभोग के साथ दोहराएं।