Computer >> कंप्यूटर ट्यूटोरियल >  >> प्रोग्रामिंग >> Redis

बकेट4जे और रेडिस के साथ स्केलेबल रेट लिमिटिंग लागू करें - चरण-दर-चरण मार्गदर्शिका

बकेट4जे और रेडिस के साथ स्केलेबल रेट लिमिटिंग लागू करें - चरण-दर-चरण मार्गदर्शिका <पी> इस ट्यूटोरियल में हम सीखेंगे कि स्केल्ड सेवा में दर सीमित कैसे लागू करें।
हम इसे लागू करने के लिए Bucket4J लाइब्रेरी का उपयोग करेंगे और हम वितरित कैश के रूप में Redis का उपयोग करेंगे।

दर सीमित का उपयोग क्यों करें?

<पी> आइए कुछ बुनियादी बातों से शुरुआत करें ताकि यह सुनिश्चित हो सके कि हम दर सीमित करने की आवश्यकता को समझते हैं और उन उपकरणों का परिचय देते हैं जिनका उपयोग हम इस ट्यूटोरियल में करेंगे।

असीमित दरों के साथ समस्या

<पी> यदि ट्विटर एपीआई जैसी कोई सार्वजनिक एपीआई अपने उपयोगकर्ताओं को प्रति घंटे असीमित संख्या में अनुरोध करने की अनुमति देती है, तो इसका परिणाम यह हो सकता है:

  • संसाधन की कमी
  • सेवा की गुणवत्ता में कमी
  • सेवा हमलों से इनकार
<पी> इसके परिणामस्वरूप ऐसी स्थिति उत्पन्न हो सकती है जहांसेवा अनुपलब्ध या धीमी हो . इससे अधिक अनपेक्षित लागतें भी आ सकती हैं सेवा द्वारा व्यय किया जा रहा है.

दर सीमित करने से कैसे मदद मिलती है

<पी> सबसे पहले, दर-सीमित करने से सेवा हमलों से इनकार को रोका जा सकता है। जब एक डिडुप्लीकेशन तंत्र या एपीआई कुंजियों के साथ जोड़ा जाता है, तो दर सीमित करने से सेवा हमलों के वितरित इनकार को रोकने में भी मदद मिल सकती है।

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

<पी> और तीसरा, आप इसका उपयोग टियर-आधारित मूल्य निर्धारण को लागू करने के लिए कर सकते हैं। इस प्रकार के मूल्य निर्धारण मॉडल का अर्थ है कि उपयोगकर्ता अनुरोधों की उच्च दर के लिए भुगतान कर सकते हैं। ट्विटर एपीआई इसका एक उदाहरण है।

टोकन बकेट एल्गोरिथम

<पी> टोकन बकेट एक एल्गोरिदम है जिसका उपयोग आप दर सीमित करने के लिए कर सकते हैं। संक्षेप में, यह इस प्रकार काम करता है:

  1. एक बाल्टी एक निश्चित क्षमता (टोकन की संख्या) के साथ बनाई जाती है।
  2. जब कोई अनुरोध आता है, तो बकेट की जाँच की जाती है। यदि पर्याप्त क्षमता है, तो अनुरोध को आगे बढ़ने की अनुमति दी जाती है। अन्यथा, अनुरोध अस्वीकार कर दिया जाता है।
  3. जब किसी अनुरोध को अनुमति दी जाती है, तो क्षमता कम हो जाती है।
  4. एक निश्चित समय के बाद, क्षमता पुनः भर दी जाती है।

वितरित सिस्टम में टोकन बकेट कैसे लागू करें

<पी> एक वितरित सिस्टम में टोकन बकेट एल्गोरिदम को लागू करने के लिए, हमें वितरित कैश का उपयोग करने की आवश्यकता है .

<पी> कैश एक की-वैल्यू स्टोर है बकेट जानकारी संग्रहीत करने के लिए. इसे लागू करने के लिए हम रेडिस कैश का उपयोग करेंगे।

<पी> आंतरिक रूप से, Bucket4j हमें Java JCache API के किसी भी कार्यान्वयन में प्लग इन करने की अनुमति देता है। रेडिस का रेडिसन क्लाइंट वह कार्यान्वयन है जिसका हम उपयोग करेंगे।

परियोजना कार्यान्वयन

<पी> हम अपनी सेवा बनाने के लिए स्प्रिंग बूट फ्रेमवर्क का उपयोग करेंगे।

<पी> हमारी सेवा में निम्नलिखित घटक शामिल होंगे:

  1. एक सरल REST API।
  2. रेडिसन क्लाइंट का उपयोग करके - सेवा से जुड़ा एक रेडिस कैश।
  3. Bucket4J लाइब्रेरी REST API के चारों ओर लिपटी हुई है।
  4. हम Bucket4J को JCache इंटरफ़ेस से कनेक्ट करेंगे जो पृष्ठभूमि में कार्यान्वयन के रूप में Redisson क्लाइंट का उपयोग करेगा।
<पी> सबसे पहले, हम सभी अनुरोधों के लिए एपीआई को रेट लिमिट करना सीखेंगे। फिर हम प्रति उपयोगकर्ता या प्रति मूल्य निर्धारण स्तर पर अधिक जटिल दर सीमित तंत्र लागू करना सीखेंगे।

<पी> आइए प्रोजेक्ट सेटअप से शुरुआत करें।

निर्भरताएं स्थापित करें

<पी> आइए नीचे दी गई निर्भरताएँ हमारे pom.xml में जोड़ें (या build.gradle ) फ़ाइल.

<dependencies>
 <!-- To build the Rest API -->
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <!-- Redisson Starter = Spring Data Redis starter(excluding other clients) and Redisson client -->
 <dependency>
 <groupId>org.redisson</groupId>
 <artifactId>redisson-spring-boot-starter</artifactId>
 <version>3.17.0</version>
 </dependency>
 <!-- Bucket4J starter = Bucket4J + JCache -->
 <dependency>
 <groupId>com.giffing.bucket4j.spring.boot.starter</groupId>
 <artifactId>bucket4j-spring-boot-starter</artifactId>
 <version>0.5.2</version>
 </dependency>
</dependencies>

कैश कॉन्फ़िगरेशन

<पी> सबसे पहले, हमें अपना रेडिस सर्वर शुरू करना होगा। मान लीजिए कि हमारी स्थानीय मशीन पर पोर्ट 6379 पर एक रेडिस सर्वर चल रहा है।

<पी> हमें दो चरण पूरे करने होंगे:

  1. हमारे एप्लिकेशन से इस सर्वर से एक कनेक्शन बनाएं।
  2. Redisson क्लाइंट को कार्यान्वयन के रूप में उपयोग करने के लिए JCache सेट करें।
<पी> रेडिसन का दस्तावेज़ नियमित जावा एप्लिकेशन में इसे लागू करने के लिए संक्षिप्त चरण प्रदान करता है। हम वही चरण लागू करने जा रहे हैं, लेकिन स्प्रिंग बूट में।

<पी> आइए पहले कोड को देखें। आवश्यक बीन्स बनाने के लिए हमें एक कॉन्फ़िगरेशन क्लास बनाने की आवश्यकता है।

@Configuration
public class RedisConfig {
 @Bean
 public Config config() {
 Config config = new Config();
 config.useSingleServer().setAddress("redis://localhost:6379");
 return config;
 }
 @Bean
 public CacheManager cacheManager(Config config) {
 CacheManager manager = Caching.getCachingProvider().getCacheManager();
 cacheManager.createCache("cache", RedissonConfiguration.fromConfig(config));
 return cacheManager;
 }
 @Bean
 ProxyManager<String> proxyManager(CacheManager cacheManager) {
 return new JCacheProxyManager<>(cacheManager.getCache("cache"));
 }
}
<पी> यह क्या करता है?
  1. एक कॉन्फ़िगरेशन ऑब्जेक्ट बनाता है जिसका उपयोग हम कनेक्शन बनाने के लिए कर सकते हैं।
  2. कॉन्फ़िगरेशन ऑब्जेक्ट का उपयोग करके कैश मैनेजर बनाता है। यह आंतरिक रूप से रेडिस इंस्टेंस से एक कनेक्शन बनाएगा और उस पर "कैश" नामक एक हैश बनाएगा।
  3. एक प्रॉक्सी मैनेजर बनाता है जिसका उपयोग कैश तक पहुंचने के लिए किया जाएगा। जो कुछ भी हमारा एप्लिकेशन JCache API का उपयोग करके कैश करने का प्रयास करता है, उसे "कैश" नामक हैश के अंदर रेडिस इंस्टेंस पर कैश किया जाएगा।

एपीआई बनाएं

<पी> आइए एक सरल REST API बनाएं।

@RestController
public class RateLimitController {
 @GetMapping("/user/{id}")
 public String getInfo(@PathVariable("id") String id) {
 return "Hello " + id;
 }
}
<पी> यदि मैं यूआरएल http://localhost:8080/user/1 के साथ एपीआई को हिट करता हूं , मुझे प्रतिक्रिया मिलेगी Hello 1 .

बकेट4J कॉन्फ़िगरेशन

<पी> दर सीमित करने को लागू करने के लिए, हमें Bucket4J को कॉन्फ़िगर करने की आवश्यकता है। शुक्र है, स्टार्टर लाइब्रेरी के कारण हमें कोई बॉयलरप्लेट कोड लिखने की आवश्यकता नहीं है।

<पी> यह स्वचालित रूप से ProxyManager बीन का भी पता लगाता है हमने पिछले चरण में बनाया था और इसका उपयोग बकेट को कैश करने के लिए किया था।

<पी> हमें जो करने की ज़रूरत है वह इस लाइब्रेरी को हमारे द्वारा बनाए गए एपीआई के आसपास कॉन्फ़िगर करना है।
फिर ऐसा करने के कई तरीके हैं।

<पी> हम संपत्ति-आधारित कॉन्फ़िगरेशन के लिए जा सकते हैं जिसे स्टार्टर लाइब्रेरी में परिभाषित किया गया है।
यह सभी उपयोगकर्ताओं या सभी अतिथि उपयोगकर्ताओं के लिए दर-सीमित करने जैसे सरल मामलों के लिए सबसे सुविधाजनक तरीका है।

<पी> हालाँकि, यदि हम प्रत्येक उपयोगकर्ता के लिए दर सीमा जैसी कुछ अधिक जटिल चीज़ लागू करना चाहते हैं, तो इसके लिए कस्टम कोड लिखना बेहतर है।

<पी> हम प्रति उपयोगकर्ता दर सीमित करने जा रहे हैं। आइए मान लें कि हमारे पास डेटाबेस में संग्रहीत प्रत्येक उपयोगकर्ता के लिए दर सीमा है, और हम उपयोगकर्ता आईडी का उपयोग करके इसे क्वेरी कर सकते हैं।

<पी> चलिए इसके लिए चरण दर चरण कोड लिखते हैं।

एक बाल्टी बनाएं

<पी> शुरू करने से पहले, आइए देखें कि बाल्टी कैसे बनाई जाती है।

Refill refill = Refill.intervally(10, Duration.ofMinutes(1));
Bandwidth limit = Bandwidth.classic(10, refill);
Bucket bucket = Bucket4j.builder()
 .addLimit(limit)
 .build();
  • फिर से भरना – कितने समय बाद बाल्टी दोबारा भर जाएगी.
  • बैंडविड्थ – बाल्टी में कितनी बैंडविड्थ है. मूलतः, प्रति रिफिल अवधि के लिए अनुरोध।
  • बाल्टी - इन दो मापदंडों का उपयोग करके एक ऑब्जेक्ट कॉन्फ़िगर किया गया है। इसके अतिरिक्त, यह बाल्टी में कितने टोकन उपलब्ध हैं, इसका ट्रैक रखने के लिए एक टोकन काउंटर रखता है।
<पी> इसे बिल्डिंग ब्लॉक के रूप में उपयोग करते हुए, आइए इसे हमारे उपयोग के मामले में उपयुक्त बनाने के लिए कुछ चीजें बदलें।

प्रॉक्सीमैनेजर का उपयोग करके बकेट बनाएं और कैश करें

<पी> हमने Redis पर बकेट संग्रहीत करने के उद्देश्य से प्रॉक्सी प्रबंधक बनाया। एक बार बकेट बन जाने के बाद, इसे Redis पर कैश करने की आवश्यकता होती है और इसे दोबारा बनाने की आवश्यकता नहीं होती है।

<पी> ऐसा करने के लिए, हम Bucket4j.builder() को प्रतिस्थापित करेंगे proxyManager.builder() के साथ . ProxyManager बकेट को कैशिंग करने और उन्हें दोबारा न बनाने का ध्यान रखेगा।

<पी> ProxyManager का बिल्डर दो पैरामीटर लेता है - एक कुंजी जिसके विरुद्ध बकेट कैश किया जाएगा और एक कॉन्फ़िगरेशन ऑब्जेक्ट होगा इसका उपयोग यह बाल्टी बनाने के लिए करेगा।

<पी> आइए देखें कि हम इसे कैसे लागू कर सकते हैं:

@Service
public class RateLimiter {
 //autowiring dependencies
 public Bucket resolveBucket(String key) {
 Supplier<BucketConfiguration> configSupplier = getConfigSupplierForUser(key);
 // Does not always create a new bucket, but instead returns the existing one if it exists.
 return buckets.builder().build(key, configSupplier);
 }
 private Supplier<BucketConfiguration> getConfigSupplierForUser(String key) {
 User user = userRepository.findById(userId);
 Refill refill = Refill.intervally(user.getLimit(), Duration.ofMinutes(1));
 Bandwidth limit = Bandwidth.classic(user.getLimit(), refill);
 return () -> (BucketConfiguration.builder()
 .addLimit(limit)
 .build());
 }
}
<पी> हमने एक विधि बनाई है जो प्रदान की गई कुंजी के लिए एक बाल्टी लौटाती है। अगले चरण में हम देखेंगे कि इसका उपयोग कैसे करना है।

टोकन का उपभोग कैसे करें और दर सीमित कैसे करें

<पी> जब कोई अनुरोध आता है, तो हम संबंधित बकेट से एक टोकन का उपभोग करने का प्रयास करेंगे।
हम tryConsume() का उपयोग करेंगे ऐसा करने के लिए बाल्टी की विधि.

@GetMapping("/user/{id}")
public String getInfo(@PathVariable("id") String id) {
 // gets the bucket for the user
 Bucket bucket = rateLimiter.resolveBucket(id);
 // tries to consume a token from the bucket
 if (bucket.tryConsume(1)) {
 return "Hello " + id;
 } else {
 return "Rate limit exceeded";
 }
}
<पी> tryConsume() विधि true लौटाती है यदि टोकन सफलतापूर्वक उपभोग किया गया था या false यदि टोकन का उपभोग नहीं किया गया था।

हमारी सेवा का परीक्षण कैसे करें

<पी> हम किसी भी स्वचालित परीक्षण तकनीक का उपयोग करके इसका परीक्षण कर सकते हैं। उदाहरण के लिए, हम JUnit का उपयोग कर सकते हैं। आइए एक परीक्षण केस लिखें जो getInfo() को कॉल करता है विधि को कई बार जांचें और सत्यापित करें कि प्रतिक्रिया सही है।

<पी> आइए मान लें कि हमारे पास आईडी 1 वाला एक उपयोगकर्ता है और 10 की सीमा प्रति मिनट अनुरोध। आइए मान लें कि हमारे पास आईडी 2 वाला एक उपयोगकर्ता भी है और 20 की सीमा प्रति मिनट अनुरोध.

<पी> हम दोनों उपयोगकर्ताओं के लिए 11 अनुरोधों को पूरा करेंगे और सत्यापित करेंगे कि अनुरोध आईडी 1 वाले उपयोगकर्ता के लिए विफल हो गया है। लेकिन आईडी 2 वाले उपयोगकर्ता के लिए सफल होता है .

@Test
public void testGetInfo() {
 // calls the method 10 times for user 1
 for (int i = 0; i < 10; i++) {
 rateLimiter.getInfo(1));
 rateLimiter.getInfo(2));
 }
 // verifies that the response is rate limited for user 1
 assertEquals("Rate limit exceeded", rateLimiter.getInfo(1));
 // verifies that the response is successful for user 2
 assertEquals("Hello 2", rateLimiter.getInfo(2));
}
<पी> जब हम परीक्षण चलाते हैं, तो हम देखेंगे कि परीक्षण सफल हो गया है।

निष्कर्ष

<पी> इस ट्यूटोरियल में, हमने स्प्रिंग बूट एप्लिकेशन में Bucket4j और Redis का उपयोग करके रेट लिमिटर बनाने का तरीका बताया है। हमने यह भी देखा कि JCache के साथ Redisson क्लाइंट कैसे सेट करें और बकेट को कैश करने के लिए इसका उपयोग कैसे करें।

<पी> अंत में, हमने एक सरल दर सीमक लागू किया जिसका उपयोग विशिष्ट उपयोगकर्ताओं के लिए दर सीमा अनुरोधों के लिए किया जा सकता है।

<पी> आशा है आपको यह ट्यूटोरियल पसंद आया होगा। पढ़ने के लिए धन्यवाद!

<पी> मुफ़्त में कोड करना सीखें. फ्रीकोडकैंप के ओपन सोर्स पाठ्यक्रम ने 40,000 से अधिक लोगों को डेवलपर्स के रूप में नौकरी पाने में मदद की है। आरंभ करें


  1. CSS का उपयोग करके सही बॉर्डर का रंग सेट करें CSS का उपयोग करके सही बॉर्डर का रंग सेट करें

    दाएँ बॉर्डर का रंग सेट करने के लिए, बॉर्डर-दायाँ-रंग . का उपयोग करें संपत्ति। आप बॉर्डर-रंग-प्रॉपर्टी को लागू करने के लिए निम्न कोड चलाने का प्रयास कर सकते हैं - उदाहरण <!DOCTYPE html> <html>    <head>       <style>          p

  1. कैसे जावास्क्रिप्ट का उपयोग कर JSON सरणी से डेटा पढ़ने के लिए? कैसे जावास्क्रिप्ट का उपयोग कर JSON सरणी से डेटा पढ़ने के लिए?

    जावास्क्रिप्ट का उपयोग करके JSON सरणी से डेटा पढ़ने के लिए निम्नलिखित कोड है - उदाहरण <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <ti

  1. लिनक्स के लिए आवश्यक कमांड-लाइन टेक्स्ट संपादक:बिल्कुल सही संपादक चुनें लिनक्स के लिए आवश्यक कमांड-लाइन टेक्स्ट संपादक:बिल्कुल सही संपादक चुनें

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