স্প্রিং ওয়েবফ্লাক্স হল একটি প্রতিক্রিয়াশীল, নন-ব্লকিং ওয়েব ফ্রেমওয়ার্ক যা জাভাতে আধুনিক, মাপযোগ্য ওয়েব অ্যাপ্লিকেশন তৈরির জন্য। এটি স্প্রিং ফ্রেমওয়ার্কের একটি অংশ, এবং এটি জাভাতে প্রতিক্রিয়াশীল প্রোগ্রামিং বাস্তবায়নের জন্য রিঅ্যাক্টর লাইব্রেরি ব্যবহার করে।
WebFlux-এর সাহায্যে, আপনি উচ্চ-কার্যক্ষমতা সম্পন্ন, মাপযোগ্য ওয়েব অ্যাপ্লিকেশন তৈরি করতে পারেন যা বিপুল সংখ্যক একযোগে অনুরোধ এবং ডেটার স্ট্রীম পরিচালনা করতে পারে। এটি সাধারণ REST API থেকে শুরু করে রিয়েল-টাইম ডেটা স্ট্রিমিং এবং সার্ভার-প্রেরিত ইভেন্টগুলিতে বিস্তৃত ব্যবহারের ক্ষেত্রে সমর্থন করে।
স্প্রিং ওয়েবফ্লাক্স প্রতিক্রিয়াশীল স্ট্রীমগুলির উপর ভিত্তি করে একটি প্রোগ্রামিং মডেল সরবরাহ করে, যা আপনাকে ডেটা প্রক্রিয়াকরণ পর্যায়ের একটি পাইপলাইনে অ্যাসিঙ্ক্রোনাস এবং নন-ব্লকিং ক্রিয়াকলাপ রচনা করতে দেয়। এটি প্রতিক্রিয়াশীল ওয়েব অ্যাপ্লিকেশন তৈরির জন্য বৈশিষ্ট্য এবং সরঞ্জামগুলির একটি সমৃদ্ধ সেট সরবরাহ করে, যার মধ্যে প্রতিক্রিয়াশীল ডেটা অ্যাক্সেস, প্রতিক্রিয়াশীল সুরক্ষা এবং প্রতিক্রিয়াশীল পরীক্ষার জন্য সমর্থন রয়েছে।
অফিসিয়াল স্প্রিং ডক থেকে:
"প্রতিক্রিয়াশীল" শব্দটি এমন প্রোগ্রামিং মডেলগুলিকে বোঝায় যা পরিবর্তনের প্রতিক্রিয়ার চারপাশে তৈরি করা হয় — নেটওয়ার্ক উপাদানগুলি I/O ইভেন্টগুলিতে প্রতিক্রিয়া জানায়, UI কন্ট্রোলারগুলি মাউস ইভেন্টগুলিতে প্রতিক্রিয়া জানায় এবং অন্যান্য। সেই অর্থে, নন-ব্লকিং প্রতিক্রিয়াশীল, কারণ, ব্লক হওয়ার পরিবর্তে, আমরা এখন ক্রিয়াকলাপ সম্পূর্ণ বা ডেটা উপলব্ধ হওয়ার সাথে সাথে বিজ্ঞপ্তিগুলিতে প্রতিক্রিয়া করার মোডে আছি।
প্রতিক্রিয়াশীল প্রোগ্রামিংয়ের মূল বৈশিষ্ট্যগুলির মধ্যে একটি হল এর থ্রেডিং মডেল, যা অনেক সিঙ্ক্রোনাস ওয়েব ফ্রেমওয়ার্কে ব্যবহৃত প্রথাগত থ্রেড-প্রতি-অনুরোধ মডেল থেকে আলাদা।
প্রথাগত মডেলে, প্রতিটি আগত অনুরোধ পরিচালনা করার জন্য একটি নতুন থ্রেড তৈরি করা হয় এবং অনুরোধটি প্রক্রিয়া না হওয়া পর্যন্ত সেই থ্রেডটি ব্লক করা হয়। এটি উচ্চ পরিমাণের অনুরোধের সাথে কাজ করার সময় স্কেলেবিলিটি সমস্যাগুলির দিকে নিয়ে যেতে পারে, কারণ অনুরোধগুলি পরিচালনা করার জন্য প্রয়োজনীয় থ্রেডের সংখ্যা খুব বড় হয়ে উঠতে পারে এবং থ্রেড প্রসঙ্গ স্যুইচিং একটি বাধা হয়ে উঠতে পারে।
বিপরীতে, WebFlux একটি নন-ব্লকিং, ইভেন্ট-চালিত মডেল ব্যবহার করে, যেখানে অল্প সংখ্যক থ্রেড বিপুল সংখ্যক অনুরোধ পরিচালনা করতে পারে। যখন একটি অনুরোধ আসে, তখন এটি উপলব্ধ থ্রেডগুলির মধ্যে একটি দ্বারা পরিচালিত হয়, যা প্রকৃত প্রক্রিয়াকরণকে অসিঙ্ক্রোনাস টাস্কগুলির একটি সেটে অর্পণ করে। এই কাজগুলি একটি নন-ব্লকিং পদ্ধতিতে সম্পাদিত হয়, থ্রেডটিকে অন্যান্য অনুরোধগুলি পরিচালনা করার জন্য এগিয়ে যাওয়ার অনুমতি দেয় যখন কাজগুলি ব্যাকগ্রাউন্ডে সম্পাদিত হয়।
স্প্রিং ওয়েবফ্লাক্সে (এবং সাধারণভাবে নন-ব্লকিং সার্ভার), এটা ধরে নেওয়া হয় যে অ্যাপ্লিকেশনগুলি ব্লক করে না। অতএব, নন-ব্লকিং সার্ভারগুলি অনুরোধগুলি পরিচালনা করার জন্য একটি ছোট, নির্দিষ্ট-আকারের থ্রেড পুল (ইভেন্ট লুপ কর্মী) ব্যবহার করে।
একটি ক্লাসিক সার্ভলেট কন্টেইনারের সরলীকৃত থ্রেডিং মডেল দেখতে এরকম দেখাচ্ছে:
যদিও WebFlux অনুরোধ প্রক্রিয়াকরণ কিছুটা আলাদা:
আসুন এগিয়ে যান এবং চকচকে তত্ত্বের পিছনে কি আছে তা দেখুন।
আমাদের স্প্রিং ইনিশিয়ালাইজার দ্বারা উত্পন্ন একটি সুন্দর সংক্ষিপ্ত অ্যাপ দরকার। কোডটি GitHub রেপোতে পাওয়া যায়।
সমস্ত থ্রেড-সম্পর্কিত বিষয়গুলি খুব CPU-নির্ভর। সাধারণত, প্রসেসিং থ্রেডের সংখ্যা যা অনুরোধগুলি পরিচালনা করে তা CPU কোরের সংখ্যার সাথে সম্পর্কিত । শিক্ষাগত উদ্দেশ্যে আপনি ডকার কন্টেইনার চালানোর সময় সিপিইউ সীমিত করে একটি পুলে থ্রেডের গণনা সহজেই পরিচালনা করতে পারেন:
docker run --cpus=1 -d --rm --name webflux-threading -p 8081:8080 local/webflux-threading
আপনি যদি এখনও একটি পুলে একাধিক থ্রেড দেখতে পান - তাহলে ঠিক আছে। WebFlux দ্বারা সেট করা ডিফল্ট থাকতে পারে।
আমাদের অ্যাপটি একটি সহজ ভাগ্যবান। /karma
এন্ডপয়েন্টে কল করলে আপনি balanceAdjustment
সহ 5টি রেকর্ড পাবেন। প্রতিটি সমন্বয় একটি পূর্ণসংখ্যা সংখ্যা যা আপনাকে দেওয়া কর্মের প্রতিনিধিত্ব করে। হ্যাঁ, আমরা খুব উদার কারণ অ্যাপটি শুধুমাত্র ইতিবাচক সংখ্যা তৈরি করে। দুর্ভাগ্য আর নেই!
একটি খুব মৌলিক উদাহরণ দিয়ে শুরু করা যাক. পরবর্তী নিয়ন্ত্রক পদ্ধতি 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
। কাজগুলি একটি থ্রেডে অবিলম্বে কার্যকর করা হয়েছিল যা সেগুলি জমা দিয়েছে৷ চুল্লী অন্য পুলে তাদের সময়সূচী করার জন্য কোন নির্দেশাবলী দেখেনি।
পরবর্তী অপারেশন 100ms (ওরফে ডাটাবেস ইমুলেশন) দ্বারা নির্গত প্রতিটি উপাদানকে বিলম্বিত করতে চলেছে
@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
সময়সূচী কি ?এটি একটি থ্রেড পুল যা গতিশীলভাবে কাজের চাপের উপর ভিত্তি করে কর্মী থ্রেডের সংখ্যা সমন্বয় করে। এটি ডাটাবেস ক্যোয়ারী এবং নেটওয়ার্ক অনুরোধের মতো I/O-বাউন্ড কাজগুলির জন্য অপ্টিমাইজ করা হয়েছে এবং খুব বেশি থ্রেড তৈরি না করে বা সম্পদ নষ্ট না করে প্রচুর স্বল্পকালীন কাজ পরিচালনা করার জন্য ডিজাইন করা হয়েছে।
ডিফল্টরূপে, boundedElastic
থ্রেড পুলটিতে উপলব্ধ প্রসেসরের সংখ্যার সর্বোচ্চ আকার 10 দ্বারা গুণিত হয় , তবে আপনি প্রয়োজনে একটি ভিন্ন সর্বোচ্চ আকার ব্যবহার করার জন্য এটি কনফিগার করতে পারেন
boundedElastic
এর মতো একটি অ্যাসিঙ্ক্রোনাস থ্রেড পুল ব্যবহার করে, আপনি থ্রেডগুলিকে আলাদা করার জন্য কাজগুলি অফলোড করতে পারেন এবং অন্যান্য অনুরোধগুলি পরিচালনা করার জন্য প্রধান থ্রেডটি খালি করতে পারেন। থ্রেড পুলের আবদ্ধ প্রকৃতি থ্রেড অনাহার এবং অত্যধিক সম্পদ ব্যবহার প্রতিরোধ করতে পারে, যখন পুলের স্থিতিস্থাপকতা এটিকে কাজের চাপের উপর ভিত্তি করে গতিশীলভাবে কর্মী থ্রেডের সংখ্যা সামঞ্জস্য করতে দেয়।
বাক্সের বাইরের শিডিউলার ক্লাস দ্বারা আরও দুটি ধরণের পুল সরবরাহ করা হয়, যেমন:
single
: এটি একটি একক-থ্রেডেড, সিরিয়ালাইজড এক্সিকিউশন প্রসঙ্গ যা সিঙ্ক্রোনাস এক্সিকিউশনের জন্য ডিজাইন করা হয়েছে। এটি উপযোগী হয় যখন আপনি নিশ্চিত করতে চান যে একটি টাস্ক ক্রমানুসারে সম্পাদিত হয়েছে এবং কোন দুটি কাজ একই সাথে সম্পাদিত হচ্ছে না।
immediate
: এটি একটি শিডিউলারের একটি তুচ্ছ, নো-অপ ইমপ্লিমেন্টেশন যা অবিলম্বে কলিং থ্রেডে কোনো থ্রেড স্যুইচিং ছাড়াই কার্য সম্পাদন করে।
স্প্রিং ওয়েবফ্লাক্সে থ্রেডিং মডেলটি নন-ব্লকিং এবং অ্যাসিঙ্ক্রোনাস করার জন্য ডিজাইন করা হয়েছে, যা ন্যূনতম রিসোর্স ব্যবহারের সাথে বিপুল সংখ্যক অনুরোধের দক্ষ পরিচালনার অনুমতি দেয়। সংযোগ প্রতি ডেডিকেটেড থ্রেডের উপর নির্ভর করার পরিবর্তে, WebFlux ইনকামিং অনুরোধগুলি পরিচালনা করতে এবং বিভিন্ন থ্রেড পুল থেকে কর্মী থ্রেডগুলিতে কাজ বিতরণ করতে অল্প সংখ্যক ইভেন্ট লুপ থ্রেড ব্যবহার করে।
যাইহোক, থ্রেড অনাহার এড়াতে এবং সিস্টেম সংস্থানগুলির দক্ষ ব্যবহার নিশ্চিত করতে আপনার ব্যবহারের ক্ষেত্রে সঠিক থ্রেড পুলটি বেছে নেওয়া গুরুত্বপূর্ণ।