स्प्रिंग जावा में आधुनिक, स्केलेबल वेब एप्लिकेशन बनाने के लिए एक प्रतिक्रियाशील, गैर-अवरुद्ध वेब ढांचा है। यह स्प्रिंग फ्रेमवर्क का एक हिस्सा है, और यह जावा में प्रतिक्रियाशील प्रोग्रामिंग को लागू करने के लिए रिएक्टर लाइब्रेरी का उपयोग करता है। वेबफ्लक्स WebFlux के साथ, आप उच्च-प्रदर्शन, स्केलेबल वेब एप्लिकेशन बना सकते हैं जो बड़ी संख्या में समवर्ती अनुरोधों और डेटा की धाराओं को संभाल सकते हैं। यह सरल REST API से लेकर रीयल-टाइम डेटा स्ट्रीमिंग और सर्वर-भेजे गए ईवेंट तक उपयोग के मामलों की एक विस्तृत श्रृंखला का समर्थन करता है। स्प्रिंग वेबफ्लक्स प्रतिक्रियाशील धाराओं के आधार पर एक प्रोग्रामिंग मॉडल प्रदान करता है, जो आपको डेटा प्रोसेसिंग चरणों की एक पाइपलाइन में अतुल्यकालिक और गैर-अवरुद्ध संचालन की रचना करने की अनुमति देता है। यह प्रतिक्रियाशील वेब अनुप्रयोगों के निर्माण के लिए सुविधाओं और उपकरणों का एक समृद्ध सेट भी प्रदान करता है, जिसमें प्रतिक्रियाशील डेटा एक्सेस, प्रतिक्रियाशील सुरक्षा और प्रतिक्रियाशील परीक्षण के लिए समर्थन शामिल है। से: आधिकारिक वसंत दस्तावेज़ शब्द, "प्रतिक्रियाशील," उन प्रोग्रामिंग मॉडल को संदर्भित करता है जो परिवर्तन पर प्रतिक्रिया करने के लिए बनाए गए हैं - नेटवर्क घटक I / O घटनाओं पर प्रतिक्रिया करते हैं, यूआई नियंत्रक माउस घटनाओं पर प्रतिक्रिया करते हैं, और अन्य। इस अर्थ में, गैर-अवरुद्ध प्रतिक्रियात्मक है, क्योंकि अवरुद्ध होने के बजाय, अब हम सूचनाओं पर प्रतिक्रिया करने के तरीके में हैं क्योंकि संचालन पूरा हो गया है या डेटा उपलब्ध हो गया है। थ्रेडिंग मॉडल प्रतिक्रियाशील प्रोग्रामिंग की मुख्य विशेषताओं में से एक इसका थ्रेडिंग मॉडल है, जो कई सिंक्रोनस वेब फ्रेमवर्क में उपयोग किए जाने वाले पारंपरिक थ्रेड-प्रति-अनुरोध मॉडल से अलग है। पारंपरिक मॉडल में, प्रत्येक आने वाले अनुरोध को संभालने के लिए एक नया थ्रेड बनाया जाता है, और अनुरोध संसाधित होने तक उस थ्रेड को ब्लॉक कर दिया जाता है। अनुरोधों की उच्च मात्रा से निपटने के दौरान यह स्केलेबिलिटी के मुद्दों को जन्म दे सकता है, क्योंकि अनुरोधों को संभालने के लिए आवश्यक थ्रेड्स की संख्या बहुत बड़ी हो सकती है, और थ्रेड संदर्भ स्विचिंग एक अड़चन बन सकती है। इसके विपरीत, वेबफ्लक्स एक गैर-अवरुद्ध, घटना-संचालित मॉडल का उपयोग करता है, जहां छोटी संख्या में धागे बड़ी संख्या में अनुरोधों को संभाल सकते हैं। जब कोई अनुरोध आता है, तो इसे उपलब्ध थ्रेड्स में से एक द्वारा नियंत्रित किया जाता है, जो तब वास्तविक प्रसंस्करण को अतुल्यकालिक कार्यों के एक सेट को दर्शाता है। इन कार्यों को गैर-अवरुद्ध तरीके से निष्पादित किया जाता है, जिससे थ्रेड को पृष्ठभूमि में निष्पादित होने पर अन्य अनुरोधों को संभालने के लिए आगे बढ़ने की अनुमति मिलती है। स्प्रिंग वेबफ्लक्स (और सामान्य रूप से नॉन-ब्लॉकिंग सर्वर) में, यह माना जाता है कि एप्लिकेशन ब्लॉक नहीं होते हैं। इसलिए, गैर-अवरुद्ध सर्वर अनुरोधों को संभालने के लिए एक छोटे, निश्चित आकार के थ्रेड पूल (इवेंट लूप वर्कर्स) का उपयोग करते हैं। क्लासिक सर्वलेट कंटेनर का सरलीकृत थ्रेडिंग मॉडल ऐसा दिखता है: जबकि WebFlux अनुरोध प्रसंस्करण थोड़ा अलग है: हुड के नीचे आइए आगे बढ़ते हैं और देखते हैं कि चमकदार सिद्धांत के पीछे क्या है। हमें द्वारा उत्पन्न एक बहुत ही न्यूनतर ऐप की आवश्यकता है। कोड में उपलब्ध है। स्प्रिंग इनिशियलाइज़र GitHub रेपो थ्रेड से संबंधित सभी विषय अत्यधिक CPU-निर्भर होते हैं। आमतौर पर, अनुरोधों को संभालने वाले प्रसंस्करण थ्रेड्स की संख्या की संख्या से संबंधित होती है शैक्षिक उद्देश्यों के लिए आप डॉकटर कंटेनर चलाते समय सीपीयू को सीमित करके पूल में थ्रेड्स की गिनती में आसानी से हेरफेर कर सकते हैं: CPU कोर । docker run --cpus=1 -d --rm --name webflux-threading -p 8081:8080 local/webflux-threading यदि आप अभी भी पूल में एक से अधिक थ्रेड देखते हैं - तो कोई बात नहीं। WebFlux द्वारा निर्धारित हो सकते हैं। डिफ़ॉल्ट हमारा ऐप एक साधारण ज्योतिषी है। समापन बिंदु पर कॉल करने पर आपको के साथ 5 रिकॉर्ड मिलेंगे। प्रत्येक समायोजन एक पूर्णांक संख्या है जो आपको दिए गए कर्म का प्रतिनिधित्व करता है। हां, हम बहुत उदार हैं क्योंकि ऐप केवल सकारात्मक संख्याएं उत्पन्न करता है। अब कोई दुर्भाग्य नहीं! /karma balanceAdjustment डिफ़ॉल्ट प्रसंस्करण आइए एक बहुत ही बुनियादी उदाहरण से शुरू करें। अगली नियंत्रक विधि 5 कर्म तत्वों से युक्त फ्लक्स लौटाती है। @GetMapping("/karma") public Flux<Karma> karma() { return prepareKarma() .map(Karma::new) .log(); } private Flux<Integer> prepareKarma() { Random random = new Random(); return Flux.fromStream( Stream.generate(() -> random.nextInt(10)) .limit(5)); } विधि यहाँ एक महत्वपूर्ण बात है। यह सभी रिएक्टिव स्ट्रीम सिग्नलों का अवलोकन करता है और उन्हें INFO स्तर के तहत लॉग में ट्रेस करता है। log कर्ल निम्नलिखित है: localhost:8081/karma जैसा कि हम देख सकते हैं, IO थ्रेड पूल पर प्रोसेसिंग हो रही है। थ्रेड नाम के लिए खड़ा है। कार्यों को तुरंत उस थ्रेड पर निष्पादित किया गया जिसने उन्हें सबमिट किया था। रिएक्टर उन्हें किसी अन्य पूल पर शेड्यूल करने के लिए कोई निर्देश नहीं देखा। ctor-http-nio-2 reactor-http-nio-2 देरी और समानांतर प्रसंस्करण अगला ऑपरेशन 100ms (उर्फ डेटाबेस एमुलेशन) से निकलने वाले प्रत्येक तत्व में देरी करने वाला है @GetMapping("/delayedKarma") public Flux<Karma> delayedKarma() { return karma() .delayElements(Duration.ofMillis(100)); } हमें यहां विधि जोड़ने की आवश्यकता नहीं है क्योंकि यह पहले से ही मूल कॉल में घोषित किया गया था। log karma() लॉग में हम अगली तस्वीर देख सकते हैं: इस बार आईओ थ्रेड पर केवल पहला तत्व प्राप्त हुआ था। शेष 4 प्रसंस्करण थ्रेड पूल को समर्पित थे। reactor-http-nio-4 parallel का जावाडोक इसकी पुष्टि करता है: delayElements सिग्नल विलंबित होते हैं और समांतर डिफ़ॉल्ट शेड्यूलर पर जारी रहते हैं आप कॉल श्रृंखला में कहीं भी निर्दिष्ट करके बिना किसी देरी के समान प्रभाव प्राप्त कर सकते हैं। .subscribeOn(Schedulers.parallel()) अनुसूचक का उपयोग विभिन्न थ्रेड्स पर एक साथ कई कार्यों को निष्पादित करने की अनुमति देकर प्रदर्शन और मापनीयता में सुधार कर सकता है, जो CPU संसाधनों का बेहतर उपयोग कर सकता है और बड़ी संख्या में समवर्ती अनुरोधों को संभाल सकता है। parallel हालाँकि, यह कोड जटिलता और मेमोरी उपयोग को भी बढ़ा सकता है, और संभावित रूप से वर्कर थ्रेड्स की अधिकतम संख्या पार हो जाने पर थ्रेड पूल थकावट का कारण बन सकता है। इसलिए, थ्रेड पूल का उपयोग करने का निर्णय आवेदन की विशिष्ट आवश्यकताओं और व्यापार-नापसंद पर आधारित होना चाहिए। parallel सबचैन आइए अब एक और जटिल उदाहरण देखें। कोड अभी भी बहुत सरल और सीधा है, लेकिन आउटपुट अधिक दिलचस्प है। हम एक उपयोग करने जा रहे हैं और एक ज्योतिषी को अधिक बना रहे हैं। कर्मा के प्रत्येक उदाहरण के लिए यह मूल समायोजन को 10 से गुणा करेगा और विपरीत समायोजन उत्पन्न करेगा, प्रभावी रूप से एक संतुलित लेनदेन का निर्माण करेगा जो मूल के लिए क्षतिपूर्ति करता है। flatMap निष्पक्ष @GetMapping("/fairKarma") public Flux<Karma> fairKarma() { return delayedKarma() .flatMap(this::makeFair); } private Flux<Karma> makeFair(Karma original) { return Flux.just(new Karma(original.balanceAdjustment() * 10), new Karma(original.balanceAdjustment() * -10)) .subscribeOn(Schedulers.boundedElastic()) .log(); } जैसा कि आप देखते हैं, फ्लक्स को एक थ्रेड पूल की सदस्यता लेनी चाहिए। आइए देखें कि हमारे पास पहले दो कर्मों के लॉग में क्या है: makeFair's boundedElastic रिएक्टर IO थ्रेड पर के साथ पहले तत्व की सदस्यता लेता है balanceAdjustment=9 फिर पूल थ्रेड पर और समायोजन उत्सर्जित करके कर्म निष्पक्षता पर काम करता है boundedElastic boundedElastic-1 90 -90 पहले वाले के बाद के तत्वों को समानांतर थ्रेड पूल पर सब्सक्राइब किया गया है (क्योंकि हमारे पास अभी भी श्रृंखला में हैं) delayedElements शेड्यूलर boundedElastic क्या है ? यह एक थ्रेड पूल है जो वर्कलोड के आधार पर वर्कर थ्रेड्स की संख्या को गतिशील रूप से समायोजित करता है। यह I/O-बाध्य कार्यों के लिए अनुकूलित है, जैसे डेटाबेस क्वेरीज़ और नेटवर्क अनुरोध, और बहुत अधिक थ्रेड्स या संसाधनों को बर्बाद किए बिना बड़ी संख्या में अल्पकालिक कार्यों को संभालने के लिए डिज़ाइन किया गया है। डिफ़ॉल्ट रूप से, थ्रेड पूल में उपलब्ध प्रोसेसर की संख्या का अधिकतम आकार 10 से गुणा होता , लेकिन यदि आवश्यक हो तो आप इसे एक अलग अधिकतम आकार का उपयोग करने के लिए कॉन्फ़िगर कर सकते हैं। boundedElastic है जैसे अतुल्यकालिक थ्रेड पूल का उपयोग करके, आप थ्रेड्स को अलग करने के लिए कार्यों को ऑफ़लोड कर सकते हैं और अन्य अनुरोधों को संभालने के लिए मुख्य थ्रेड को मुक्त कर सकते हैं। थ्रेड पूल की बंधी हुई प्रकृति थ्रेड भुखमरी और अत्यधिक संसाधन उपयोग को रोक सकती है, जबकि पूल की लोच इसे कार्यभार के आधार पर गतिशील रूप से वर्कर थ्रेड्स की संख्या को समायोजित करने की अनुमति देती है। boundedElastic अन्य प्रकार के थ्रेड पूल आउट-ऑफ़-द-बॉक्स वर्ग द्वारा दो और प्रकार के पूल प्रदान किए जाते हैं, जैसे: शेड्यूलर : यह एक एकल-थ्रेडेड, क्रमबद्ध निष्पादन संदर्भ है जिसे तुल्यकालिक निष्पादन के लिए डिज़ाइन किया गया है। यह तब उपयोगी होता है जब आपको यह सुनिश्चित करने की आवश्यकता होती है कि किसी कार्य को क्रम में निष्पादित किया जाता है और कोई भी दो कार्य समवर्ती रूप से निष्पादित नहीं किए जाते हैं। single : यह शेड्यूलर का एक तुच्छ, नो-ऑप कार्यान्वयन है जो कॉलिंग थ्रेड पर बिना किसी थ्रेड स्विचिंग के कार्यों को तुरंत निष्पादित करता है। immediate निष्कर्ष स्प्रिंग वेबफ्लक्स में थ्रेडिंग मॉडल को गैर-अवरुद्ध और अतुल्यकालिक होने के लिए डिज़ाइन किया गया है, जो न्यूनतम संसाधन उपयोग के साथ बड़ी संख्या में अनुरोधों को कुशल तरीके से संभालने की अनुमति देता है। प्रति कनेक्शन समर्पित थ्रेड्स पर भरोसा करने के बजाय, आने वाले अनुरोधों को संभालने और विभिन्न थ्रेड पूल से वर्कर थ्रेड्स को काम वितरित करने के लिए WebFlux इवेंट लूप थ्रेड्स की एक छोटी संख्या का उपयोग करता है। हालांकि, थ्रेड भुखमरी से बचने और सिस्टम संसाधनों के कुशल उपयोग को सुनिश्चित करने के लिए अपने उपयोग के मामले में सही थ्रेड पूल चुनना महत्वपूर्ण है।