जब आपका API हांफने लगे: रेट लिमिटिंग का परिचय
\n\nएक स्थिति की कल्पना करें: आपने C++ में एक आदर्श सर्वर लिखा है। यह तेज़, कुशल है, और प्रोसेसर के सभी कोर का उपयोग करता है। आप इसे प्रोडक्शन में चलाते हैं, और... पाँच मिनट बाद यह क्रैश हो जाता है। क्या हुआ? पता चला, किसी शरारती स्क्रिप्ट ने आपके API को 'जांचने' का फैसला किया, प्रति सेकंड हजारों अनुरोध भेजे।
\n\nपरिचित लगता है? यदि नहीं, तो आप भाग्यशाली हैं। लेकिन देर-सबेर हर डेवलपर को लोड को नियंत्रित करने की आवश्यकता का सामना करना पड़ता है। यहीं पर रेट लिमिटिंग और थ्रॉटलिंग आते हैं - दो शक्तिशाली तंत्र जो सर्वर को ओवरलोड से बचाते हैं और संसाधनों का समान वितरण सुनिश्चित करते हैं।
\n\nइस लेख में, हम समझेंगे कि C++ में इन तंत्रों को कैसे लागू किया जाए। आप न केवल सिद्धांत सीखेंगे, बल्कि कार्यशील कोड भी प्राप्त करेंगे जिसे आप तुरंत अपने प्रोजेक्ट में उपयोग कर सकते हैं। चलिए शुरू करते हैं!
\n\nरेट लिमिटिंग बनाम थ्रॉटलिंग: क्या अंतर है?
\n\nकोड में गोता लगाने से पहले, आइए इन दो अवधारणाओं को स्पष्ट रूप से अलग करें। कई लोग इन्हें भ्रमित करते हैं, लेकिन अंतर है, और यह महत्वपूर्ण है।
\n\nरेट लिमिटिंग (गति सीमा)
\nयह एक 'बैरियर' है। आप कहते हैं: 'एक सेकंड में 10 से अधिक अनुरोध नहीं। इससे अधिक सब कुछ - बैन (या कतार) में।' रेट लिमिटिंग आपके API को अचानक आने वाले अनुरोधों, DDoS हमलों और ट्रैफिक के आकस्मिक उछाल से बचाता है।
\n\nथ्रॉटलिंग (नियंत्रण)
\nयह एक 'वॉल्यूम नियंत्रक' है। आप अनुरोधों को पूरी तरह से ब्लॉक नहीं करते, बल्कि उनकी प्रोसेसिंग को धीमा कर देते हैं। उदाहरण के लिए, यदि कोई क्लाइंट प्रति सेकंड 100 अनुरोध भेजता है, तो आप उन्हें प्रोसेस करते हैं, लेकिन प्रत्येक के बीच 10 मिलीसेकंड की देरी के साथ। थ्रॉटलिंग लोड प्रबंधन का एक अधिक 'विनम्र' तरीका है, यह डेटा को नहीं छोड़ता, बल्कि केवल पीक को स्मूथ करता है।
\n\nवास्तविक प्रोजेक्ट में, इन तकनीकों को अक्सर संयोजित किया जाता है: पहले स्मूथ करने के लिए थ्रॉटलिंग, और फिर महत्वपूर्ण सीमा पार होने पर 429 (Too Many Requests) त्रुटि लौटाने के साथ रेट लिमिटिंग।
\n\nC++ में रेट लिमिटिंग एल्गोरिदम
\n\nकई क्लासिक एल्गोरिदम हैं। हम दो सबसे लोकप्रिय और प्रभावी पर चर्चा करेंगे: Token Bucket और Sliding Window। दोनों को C++ में आसानी से लागू किया जा सकता है और उत्कृष्ट परिणाम देते हैं।
\n\n1. Token Bucket (टोकन बाल्टी)
\nएक बाल्टी की कल्पना करें जिसमें हर सेकंड N टोकन टपकते हैं। प्रत्येक अनुरोध एक टोकन लेता है। यदि बाल्टी खाली है - अनुरोध अस्वीकार कर दिया जाता है। सरल और शानदार।
\n\nयहाँ std::chrono का उपयोग करके आधुनिक C++ में कार्यान्वयन है:
#include <chrono>\n#include <mutex>\n#include <atomic>\n\nclass TokenBucket {\npublic:\n TokenBucket(size_t max_tokens, double refill_rate)\n : max_tokens_(max_tokens)\n , refill_rate_(refill_rate)\n , current_tokens_(max_tokens)\n , last_refill_(std::chrono::steady_clock::now()) {}\n\n bool try_consume() {\n std::lock_guard<std::mutex> lock(mutex_);\n \n // गणना करें कि पिछली बार से कितने टोकन जमा हुए हैं\n auto now = std::chrono::steady_clock::now();\n auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - last_refill_);\n \n // बाल्टी भरें\n double tokens_to_add = elapsed.count() * refill_rate_ / 1000.0;\n current_tokens_ = std::min(max_tokens_, current_tokens_ + tokens_to_add);\n last_refill_ = now;\n \n // टोकन लेने का प्रयास करें\n if (current_tokens_ > 0) {\n --current_tokens_;\n return true;\n }\n return false;\n }\n\nprivate:\n std::mutex mutex_;\n size_t max_tokens_; // बाल्टी की अधिकतम क्षमता\n double refill_rate_; // प्रति सेकंड टोकन\n double current_tokens_; // वर्तमान टोकन की संख्या\n std::chrono::steady_clock::time_point last_refill_;\n};\n\nउपयोग:
\nTokenBucket limiter(10, 1.0); // 10 टोकन, 1 टोकन/सेकंड की दर से भरना\n\n// अनुरोध हैंडलर में:\nif (limiter.tr