Node js কিভাবে কাজ করে?

Mohiuddin Mazumder
5 min readJun 17, 2021

নোড জেএস কিভাবে কাজ করে তা জানতে হলে প্রথমে জানতে হবে ওয়েব সার্ভার কিভাবেে কাজ করে।
ওয়েব সার্ভারে সাধারণত বেকেন্ডের ওয়েব এপ্লিকেশন থাকে যা দূরে থাকা কোনো একটা ক্লায়েন্ট এক্সেস করতে পারে। সেই ক্লায়েন্ট হয়ে পারে কোনো মানুষের ব্রাউজার অথবা কোনো একটা মোবাইল অ্যাপ ইত্যাদি।
যখন ক্লায়েন্ট ওয়েব ব্রাউজার তখন ক্লায়েন্ট Html এক্সপেক্ট করবে, Single page application এর ক্ষেত্রে ক্লায়েন্ট ডাটা এক্সপেক্ট করবে। যদি আমাদের ক্লায়েন্ট হয় মোবাইল অ্যাপ তখন আমরা শুধু ডাটা এক্সপেক্ট করি। যেটা সার্ভার থেকে APIএর মাধ্যমে রিকোয়েস্ট করে এক্সেস করতে পারি।
সুতরাং, ক্লায়েন্ট যাই হোক সার্ভার থেকে html অথবা ডাটা এক্সপেক্ট করি। এর জন্য সার্ভারকে আমরা প্রয়োজনমতো রিকোয়েস্ট করার পর সেই সার্ভার আরেকটা সার্ভার অথবা ডাটাবেজ অথবা ফাইল সিস্টেম কে প্রয়োজনমতো রিকোয়েস্ট করে একটা নির্দিষ্ট সময় পর আমাদের রেস্পন্স দেয়।
এখন রিকোয়েস্টটা যদি সিম্পল হয় যেমন ২+৪=কত? তখন সার্ভার খুব দ্রুত রেস্পন্স দিল ৬। এর জন্য সার্ভারকে অন্য কোথাও রিকোয়েস্ট করতে হয় নি, একে বলা হয় cpu intensive task। মানে এটা সার্ভারে cpu ই করতে পারে এর জন্য অন্য কোথাও রিকোয়েস্ট করতে হয় না।
যদি রিকোয়েস্টটা এমন হয় যেটার জন্য সার্ভারকে অন্য একটা সার্ভারে রিকোয়েস্ট করতে হবে অথবা একটা ডাটাবেজ এর এক্সেস নিতে হবে অথবা কোনো ফাইল সিস্টেম কে রিকোয়েস্ট করতে হবে। একে বলা হয় I/O intensive task।
ধরি, অন্য কোথাও থেকে রিকোয়েস্ট করে ডাটা আনতে সার্ভারের ৩ সেকেন্ড সময় লাগল। এখন ১ জন ক্লায়েন্টের জন্য যদি ৩ সেকেন্ড সময় লাগে তবে যদি ৫ জন ক্লায়েন্ট রিকোয়েস্ট করে তবেতো সময় লাগবে ১৫ সেকেন্ড। এতক্ষণ সময় নিলে ক্লায়েন্ট তো আমাদের জন্য বসে থাকবে না।
এখন প্রশ্ন আসে সার্ভার থেকে ডাটা আসতে এত সময় লাগার কারণ কি?
এর জন্য আমাদের জানতে হবে Thread সম্পর্কে। বুঝার সুবিধার্থে আমরা Thread কে একটা প্রসেস বলতে পারি।
আমরা যদি জাভার দিকে একটু লক্ষ করি, জাভার Tomcat সার্ভারে সাধারণত ২০০ টা Thread থাকে। Tomcat সার্ভারে একাধিক Thread থাকার কারণে যখনই একটা ক্লায়েন্ট একটা রিকোয়েস্ট করে তখন ঐ কাজের জন্য Tomcat সার্ভার তার একটা Thread কে এসাইন করে দেয়। আরেকটা ক্লায়েন্ট আসলে সে আরেকটা Thread কে এসাইন করে দেয়। এভাবে যদি ১০ টা রিকোয়েস্ট আসে তবে ১০ টা Thread কে সে এসাইন করে দিবে। এখানে সব Thread কে প্যারালাল ভাবে হ্যান্ডেল করা হচ্ছে যার ফলে ১ম ক্লায়েন্টের জন্য যদি ৩ সেকেন্ডে সময় লাগে ১০ জন ক্লায়েন্ট এর জন্যেও ৩ সেকেন্ডই সময় লাগবে। কিন্তু সমস্যা হচ্ছে Tomcat সার্ভারে Thread থাকে তো শুধুমাত্র ২০০ টা। এখন যদি ২০৫ তা রিকোয়েস্ট আসে তবে কি হবে? শেষ ৫ জন এর মধ্যে ৫ম ব্যাক্তির রেস্পন্স পেতে ১৫ সেকেন্ড সময় লাগবে। তার মানে এখানে অপেক্ষা করা লাগছে। যদিও tomcat এর মধ্যে Thread সংখ্যা বাড়ানো যায়, যেহেতু Node নিয়ে আলোচনা হচ্ছে তাহলে ওইদিকে না গিয়ে Node এ ফিরে আসা যাক।
আমরা জানি, Javascript single Threaded language. Node js যেহেতু জাভাস্ক্রিপ্ট এর রানটাইম তাই Node js ও অবশ্যই Single Thread ই কাজ করে।

এখন প্রশ্ন হচ্ছে জাভা যেখানে মাল্টি থ্রেড থাকা সত্ত্বেও রিকোয়েস্ট হ্যান্ডেল করতে অনেক ঝামেলায় পড়তে হচ্ছে সেখানে Node js কিভাবে Single Thread এর মাধ্যমে এতো পাওয়ারফুলভাবে মাল্টিপল রিকোয়েস্ট হ্যান্ডেল করছে?
ধরি, একটা ক্লায়েন্ট রিকোয়েস্ট করল ১+১=কত? তখন সার্ভার দ্রুত রিটার্ন করল ২। কিন্তু রিকোয়েস্টটা যদি এমন হয় যে যদি ডাটাবেজ থেকে ডাটা নিয়ে আসতে হবে বা অন্য কোনো সার্ভারে রিকোয়েস্ট করতে হবে বা ফাইল সিস্টেম কে এক্সেস করতে হবে মানে I/O intensive task কমপ্লিট করতে হবে। ধরি, এই টাস্ক কমপ্লিট করতে সার্ভারের ২ সেকেন্ড সময় লাগল। একই সময়ে আরেকজন ক্লায়েন্ট যদি রিকোয়েস্ট করে তবে ২য় ক্লায়েন্টকে তো অপেক্ষা করতে হচ্ছে। কারণ, javascript এর single Thread তো এখনও প্রথম ক্লায়েন্টকে নিয়ে ব্যাস্ত আছে। প্রথম ক্লায়েন্ট এর রেস্পন্স দেয়ার পর সে ২য় ক্লায়েন্টের রিকোয়েস্ট এক্সেপ্ট করবে। এক্ষেত্রেও মনে করি ২ সেকেন্ড সময় লাগল। মনে করি, একসাথে ১০০ রিকোয়েস্ট চলে আসল। তখন কি হবে!!!
Node js আসলে এভাবে I/O intensive task গুলা কমপ্লিট করে না। এক্ষেত্রে Node js আলাদা একটা সলিউশন ফলো করে। Node js এর Single Thread এর কাজ হচ্ছে রিকোয়েস্ট এক্সেপ্ট করা, সে শুধু রিকোয়েস্ট এক্সেপ্ট করবে, আর কিছু করবে না। তাহলে এখন প্রশ্ন হচ্ছে বাকি কাজগুলা কে করবে?
Node js এ যখন একটা রিকোয়েস্ট আসে তখন single thread রিকোয়েস্ট এক্সেপ্ট করবে ঠিকই কিন্তু অন্য সার্ভার থেকে রেস্পন্স এর জন্য ওয়েট করবে না৷
Asynchronous এবং Non-blocking I/O এই দুইটা কনসেপ্ট কে কাজে লাগিয়ে সে কাজ গুলা করে থাকে।

Non-blocking I/O:
Single thread একটা রিকোয়েস্ট এক্সেপ্ট করে আরেকজন কে রিকোয়েস্টটা পাঠিয়ে দিবে কারেন্ট Thread ঐ রিকোয়েস্ট নিয়ে ব্যাস্ত হয়ে বসে থাকবে না। ধরে নেই, আমাদের কিছু ওয়ার্কার আছে। যারা এই সার্ভারের জন্য কাজ করছে। Node js শুধুমাত্র রিকোয়েস্টটা পাস করে দিবে তার ওয়ার্কার এর কাছে। এরই মধ্যে যদি আরো রিকোয়েস্ট আসে সমস্যা নেই কারণ Node js এর Thread কিন্তু এখনও ওপেন আছে সে আবারও রিকোয়েস্ট এক্সেপ্ট করে তার ২য় ওয়ার্কার এর কাছে পাস করে দিবে। Node js এভাবে Non-blocking I/O কনসেপ্ট এ কাজ করে। এর মানে হলো সে একটা রিকোয়েস্ট এর জন্য blocked হয়ে বসে থাকবে না। I/O operation এর ক্ষেত্রে Node js Non-blocking।
কিন্তু যদি আরেকটা ক্লায়েন্ট এসে বলে আমার ১ থেকে ১০ লক্ষ পর্যন্ত সব সংখ্যার যোগফল লাগবে। এটা কিন্তু cpu কে করতে হবে। এছাড়াও এটা একটা huge cpu intensive task। এই কাজ সে কাউকে এসাইন করাতে পারবে না। Node js এর Thread এইকাজ করতে গিয়ে blocked হয়ে থাকবে। এইজন্যই বলা হয়- Node js is not suitable for cpu intensive task.
আচ্ছা আমাদের এখনও কিন্তু ক্লায়েন্টের যেসব কাজ ওয়ার্কার কে এসাইন করা হয়েছে তার রেস্পন্স ক্লায়েন্টকে দেয়া হয় নাই। ওয়ার্কার যখন রেসপন্স নিয়ে আসবে তখন রেস্পন্সকে কল করার জন্য প্রয়োজন হবে callback function এর।
মানে এখানে asynchronous way তে কাজটা করা হচ্ছে৷ মানে সিরিয়ালি, লাইন বাই লাইন কাজ না করে যে কাজটা করতে সময় লাগবে সেটার জন্য অপেক্ষা না করে পরের কাজগুলো শেষ করে যখন আগের কাজের রেসপন্স আসবে তখন callback এর মাধ্যমে কল করে এর রেজাল্ট রিটার্ন করার প্রসেসটাই হচ্ছে asynchronous।
Node js সাধারণত এভাবেই I/O task হ্যান্ডেল করে থাকে।
এখন প্রশ্ন হচ্ছে এতো সুন্দরভাবে হ্যান্ডেল করার জন্য এর পিছনে কে কাজ করে। কার কাজ কখন, কাকে কি কাজে এসাইন করতে হবে এইসব বিষয় হ্যান্ডেল করে event loop, event loop কে নন স্টপ while loop বলতে পারি। Event loop নতুন টাস্কের জন্য সারাক্ষণ ওয়েট করতে থাকে এবং একটা task queue মেন্টেইন করে সে ওয়ার্কারদের দিয়ে কাজ করিয়ে নেন।
এখন আরেকটা বিষয় হচ্ছে Node js যে ওয়ার্কার গুলা কাজ করে এইগুলা আসলে কি?
এইগুলা যদি Thread না হয় তবে কি এগুলো?
Node js এ এই ওয়ার্কার গুলা আসে libuv থেকে। Libuv হচ্ছে একটা স্পেশাল টাইপ অফ লাইব্রেরি। এটা Node js এর জন্য বানানো হলেও অন্য জায়গায় ও ব্যবহার করা হয়। এটা নরমালি Non-blocking I/O ককন্সেন্টটা দেয়। এটা c ল্যাংুয়েজ এ বানানো, এটা আমাদের কার্নেলকে ব্যবহার করে। কার্নেল মানে সেই সিস্টেম যেটা আমাদের operating system কে কন্ট্রোল করছে। এই কার্নেলের মাল্টিপল Thread আছে। Node js এ আমরা মাল্টিপল Thread ব্যবহার করছি না কিন্তু বিহাইন্ড দা সিনে libuv এর ম্যধ্যমে Node js সিস্টেম কার্নেলকে দিয়ে মাল্টিপল Thread ব্যবহার করছে। সুতরাং, এতক্ষণ যে ওয়ার্কার গুলা নিয়ে কথা হলো এইগুলা আসলে Threads।
Node js বিহাইন্ড দা সিনের এই বিউটির কারণে এতো সুপার ফাস্ট কাজ করে।

--

--