স্প্রিং ওয়েবফ্লাক্স হল একটি প্রতিক্রিয়াশীল, নন-ব্লকিং ওয়েব ফ্রেমওয়ার্ক যা জাভাতে আধুনিক, মাপযোগ্য ওয়েব অ্যাপ্লিকেশন তৈরির জন্য। এটি স্প্রিং ফ্রেমওয়ার্কের একটি অংশ, এবং এটি জাভাতে প্রতিক্রিয়াশীল প্রোগ্রামিং বাস্তবায়নের জন্য রিঅ্যাক্টর লাইব্রেরি ব্যবহার করে।
"প্রতিক্রিয়াশীল" শব্দটি এমন প্রোগ্রামিং মডেলগুলিকে বোঝায় যা পরিবর্তনের প্রতিক্রিয়ার চারপাশে তৈরি করা হয় — নেটওয়ার্ক উপাদানগুলি I/O ইভেন্টগুলিতে প্রতিক্রিয়া জানায়, UI কন্ট্রোলারগুলি মাউস ইভেন্টগুলিতে প্রতিক্রিয়া জানায় এবং অন্যান্য। সেই অর্থে, নন-ব্লকিং প্রতিক্রিয়াশীল, কারণ, ব্লক হওয়ার পরিবর্তে, আমরা এখন ক্রিয়াকলাপ সম্পূর্ণ বা ডেটা উপলব্ধ হওয়ার সাথে সাথে বিজ্ঞপ্তিগুলিতে প্রতিক্রিয়া করার মোডে আছি।
স্প্রিং ওয়েবফ্লাক্সে (এবং সাধারণভাবে নন-ব্লকিং সার্ভার), এটা ধরে নেওয়া হয় যে অ্যাপ্লিকেশনগুলি ব্লক করে না। অতএব, নন-ব্লকিং সার্ভারগুলি অনুরোধগুলি পরিচালনা করার জন্য একটি ছোট, নির্দিষ্ট-আকারের থ্রেড পুল (ইভেন্ট লুপ কর্মী) ব্যবহার করে।
যদিও WebFlux অনুরোধ প্রক্রিয়াকরণ কিছুটা আলাদা:
আমাদের দ্বারা উত্পন্ন একটি সুন্দর সংক্ষিপ্ত অ্যাপ দরকার। কোডটি পাওয়া যায়।
সমস্ত থ্রেড-সম্পর্কিত বিষয়গুলি খুব CPU-নির্ভর। সাধারণত, প্রসেসিং থ্রেডের সংখ্যা যা অনুরোধগুলি পরিচালনা করে তা CPU কোরের সংখ্যার সাথে সম্পর্কিত । শিক্ষাগত উদ্দেশ্যে আপনি ডকার কন্টেইনার চালানোর সময় সিপিইউ সীমিত করে একটি পুলে থ্রেডের গণনা সহজেই পরিচালনা করতে পারেন:
docker run --cpus=1 -d --rm --name webflux-threading -p 8081:8080 local/webflux-threading
আমাদের অ্যাপটি একটি সহজ ভাগ্যবান। /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)); }
log
পদ্ধতি এখানে একটি গুরুত্বপূর্ণ জিনিস। এটি সমস্ত প্রতিক্রিয়াশীল স্ট্রীম সংকেতগুলি পর্যবেক্ষণ করে এবং সেগুলিকে INFO স্তরের অধীনে লগগুলিতে ট্রেস করে৷
curl localhost:8081/karma
এ লগ আউটপুট নিম্নরূপ:
আমরা দেখতে পাচ্ছি, IO থ্রেড পুলে প্রক্রিয়াকরণ হচ্ছে। থ্রেডের নাম ctor-http-nio-2
এর অর্থ হল reactor-http-nio-2
। কাজগুলি একটি থ্রেডে অবিলম্বে কার্যকর করা হয়েছিল যা সেগুলি জমা দিয়েছে৷ চুল্লী অন্য পুলে তাদের সময়সূচী করার জন্য কোন নির্দেশাবলী দেখেনি।
@GetMapping("/delayedKarma") public Flux<Karma> delayedKarma() { return karma() .delayElements(Duration.ofMillis(100)); }
আমাদের এখানে log
মেথড যোগ করার দরকার নেই কারণ এটি ইতিমধ্যেই আসল karma()
কলে ঘোষণা করা হয়েছে।
এই সময় শুধুমাত্র প্রথম উপাদানটি IO থ্রেড reactor-http-nio-4
এ প্রাপ্ত হয়েছিল। বাকি 4টির প্রক্রিয়াকরণ একটি parallel
থ্রেড পুলের জন্য নিবেদিত ছিল।
delayElements
এর Javadoc এটি নিশ্চিত করে:
সংকেত বিলম্বিত হয় এবং সমান্তরাল ডিফল্ট সময়সূচীতে চলতে থাকে
আপনি কল চেইনের যেকোনো জায়গায় .subscribeOn(Schedulers.parallel())
উল্লেখ করে বিলম্ব না করে একই প্রভাব অর্জন করতে পারেন।
parallel
শিডিউলার ব্যবহার করে বিভিন্ন থ্রেডে একযোগে একাধিক কাজ চালানোর অনুমতি দিয়ে কর্মক্ষমতা এবং মাপযোগ্যতা উন্নত করতে পারে, যা CPU সংস্থানগুলিকে আরও ভালভাবে ব্যবহার করতে পারে এবং বিপুল সংখ্যক সমবর্তী অনুরোধগুলি পরিচালনা করতে পারে।
যাইহোক, এটি কোডের জটিলতা এবং মেমরির ব্যবহারকেও বাড়িয়ে তুলতে পারে এবং সম্ভাব্য থ্রেড পুল ক্লান্তির দিকে নিয়ে যেতে পারে যদি কর্মী থ্রেডের সর্বাধিক সংখ্যা অতিক্রম করা হয়। অতএব, parallel
থ্রেড পুল ব্যবহার করার সিদ্ধান্তটি আবেদনের নির্দিষ্ট প্রয়োজনীয়তা এবং ট্রেড-অফের উপর ভিত্তি করে হওয়া উচিত।
আমরা একটি flatMap
ব্যবহার করতে যাচ্ছি এবং একজন ভবিষ্যতকারীকে আরও ন্যায্য করে তুলতে যাচ্ছি। প্রতিটি কর্মের উদাহরণের জন্য এটি মূল সমন্বয়কে 10 দ্বারা গুণ করবে এবং বিপরীত সমন্বয় তৈরি করবে, কার্যকরভাবে একটি সুষম লেনদেন তৈরি করবে যা আসলটির জন্য ক্ষতিপূরণ দেবে।
@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
সময়সূচী কি ?
ডিফল্টরূপে, boundedElastic
থ্রেড পুলটিতে উপলব্ধ প্রসেসরের সংখ্যার সর্বোচ্চ আকার 10 দ্বারা গুণিত , তবে আপনি প্রয়োজনে একটি ভিন্ন সর্বোচ্চ আকার ব্যবহার করার জন্য এটি কনফিগার করতে পারেন
boundedElastic
এর মতো একটি অ্যাসিঙ্ক্রোনাস থ্রেড পুল ব্যবহার করে, আপনি থ্রেডগুলিকে আলাদা করার জন্য কাজগুলি অফলোড করতে পারেন এবং অন্যান্য অনুরোধগুলি পরিচালনা করার জন্য প্রধান থ্রেডটি খালি করতে পারেন। থ্রেড পুলের আবদ্ধ প্রকৃতি থ্রেড অনাহার এবং অত্যধিক সম্পদ ব্যবহার প্রতিরোধ করতে পারে, যখন পুলের স্থিতিস্থাপকতা এটিকে কাজের চাপের উপর ভিত্তি করে গতিশীলভাবে কর্মী থ্রেডের সংখ্যা সামঞ্জস্য করতে দেয়।
single
: এটি একটি একক-থ্রেডেড, সিরিয়ালাইজড এক্সিকিউশন প্রসঙ্গ যা সিঙ্ক্রোনাস এক্সিকিউশনের জন্য ডিজাইন করা হয়েছে। এটি উপযোগী হয় যখন আপনি নিশ্চিত করতে চান যে একটি টাস্ক ক্রমানুসারে সম্পাদিত হয়েছে এবং কোন দুটি কাজ একই সাথে সম্পাদিত হচ্ছে না।
immediate
: এটি একটি শিডিউলারের একটি তুচ্ছ, নো-অপ ইমপ্লিমেন্টেশন যা অবিলম্বে কলিং থ্রেডে কোনো থ্রেড স্যুইচিং ছাড়াই কার্য সম্পাদন করে।