क्या NodeJs सिंगल-थ्रेडेड है?

Mar 20 2023
नोडज में अन्य थ्रेड्स के साथ कैसे काम करें?
Node.js जावास्क्रिप्ट कोड को सिंगल थ्रेड में चलाता है, जिसका अर्थ है कि आपका कोड एक समय में केवल एक ही कार्य कर सकता है।
Nodejs I/O प्रक्रिया

Node.js जावास्क्रिप्ट कोड को सिंगल थ्रेड में चलाता है, जिसका अर्थ है कि आपका कोड एक समय में केवल एक ही कार्य कर सकता है। लेकिन Node.js स्वयं बहुप्रचारित है और `libuv` पुस्तकालय के माध्यम से छिपे हुए धागे प्रदान करता है, जो डिस्क या नेटवर्क अनुरोधों से फ़ाइलों को पढ़ने जैसे I/O संचालन को संभालता है। छिपे हुए थ्रेड्स के उपयोग के माध्यम से, Node.js अतुल्यकालिक तरीके प्रदान करता है जो आपके कोड को मुख्य थ्रेड को ब्लॉक किए बिना I/O अनुरोध करने की अनुमति देता है।

Node.js ने हमारे लिए वर्कर-थ्रेड मॉड्यूल पेश किया। वह मॉड्यूल समानांतर में थ्रेड बनाने और जावास्क्रिप्ट कार्यों को निष्पादित करने की अनुमति देता है। यदि कोई थ्रेड किसी कार्य को पूरा करता है, तो वह मुख्य थ्रेड को एक संदेश भेजता है जिसमें परिणाम होता है ताकि हम इसे मुख्य थ्रेड में उपयोग कर सकें। वर्कर-थ्रेड्स मुख्य थ्रेड को ब्लॉक नहीं करते हैं, इसलिए हम इसे ऑप्टिमाइज़ करने के लिए अपने टास्क को कई पार्स में विभाजित और वितरित कर सकते हैं।

आइए इसका एक उदाहरण बनाते हैं और इसे करीब से देखते हैं।

हम एक Nodejs प्रोजेक्ट बना रहे हैं और एक्सप्रेस फ्रेमवर्क स्थापित कर रहे हैं

mkdir multiple-thread
cd multiple-thread
npm init -y
npm install express

सबसे पहले, प्रक्रियाएं और धागे हैं। हमें उनके बीच के अंतरों को जानना चाहिए।

प्रक्रिया क्या है?

एक प्रक्रिया OS में एक प्रोग्राम चला रही है। यह एक समय में एक कार्य को अंजाम दे सकता है।

आइए प्रक्रिया को करीब से देखें। एक JS फाइल बनाएं और प्रक्रिया को लॉग करें।

//ex-process.js

const processName = process.argv.slice(2)[0]

let count = 0;

while(true){
 count++;
 if(count === 3333 || count=== 6666){
   console.log(`${processName}: ${count}`)
 }
}

node ex-process.js FirstEx &

// & symbol means the Node program to run in the background, so we can use 
our teminal for other works

Output
[1] 82942
FirstEx: 3333
FirstEx: 6666

ps |grep node

Output
82942 ttys001    2:38.85 node ex-process.js FirstEx
83105 ttys001    0:00.00 grep node

किसी एप्लिकेशन के अंदर निष्पादन के कई पथों को लागू करने के लिए थ्रेड अपेक्षाकृत हल्का तरीका है। सिस्टम स्तर पर, प्रोग्राम साथ-साथ चलते हैं, सिस्टम प्रत्येक प्रोग्राम को उसकी ज़रूरतों और अन्य प्रोग्राम की ज़रूरतों के आधार पर निष्पादन समय देता है।

चलो एक्सप्रेस सर्वर को नॉन-ब्लॉकिंग रूट और ब्लॉकिंग रूट के साथ कोड करते हैं

आइए उपयोगकर्ताओं के लिए एक सामान्य ब्लॉकिंग रूट को कोड करें। में app.js;

const express = require('express');

const app = express();

app.get('/hello', (req,res)=>{
    res.status(200).send(`Hello`);
})

app.get('/blocking-route', (req,res)=>{
    console.log('Blocking route called')
    let counter = 0;
    for (let i = 0; i < 15_000_000_000; i++) {
      counter++;
    }
    res.status(200).send(`result is ${counter}`);
})



app.listen(7333, ()=> console.log('Server started on port 7333'));

यह समाप्त होने तक प्रतिक्रिया नहीं देता है blocking-routeऔर प्रतिक्रिया वापस भेज दी है।

इसने हमें तुरंत जवाब क्यों नहीं दिया?

इस उदाहरण में, सीपीयू-बाउंड फॉर लूप मुख्य थ्रेड को ब्लॉक करता है। जबकि मुख्य थ्रेड अवरुद्ध है, CPU-बाध्य प्रक्रिया समाप्त होने तक Node.js किसी भी प्रश्न को संसाधित नहीं कर सकता है। इसलिए रूट लोड /helloके रूप में कार्य करने वाले अन्य मार्गों में से कोई भी नहीं ।/blocking-route

GETइस प्रकार, यदि हमारे पास एक एपीआई है जिसमें गैर-अवरुद्ध मार्ग जैसे हजारों एक साथ अनुरोध हैं /hello, तो /blocking-routeएपीआई में सभी मार्गों को अवरुद्ध करने के लिए केवल एक अनुरोध होगा। इसका मतलब है, यह सभी आवेदन मार्गों को गैर-प्रतिक्रियाशील बनाता है।

DAAA IT की जावास्क्रिप्ट, हम अन्य थ्रेड का उपयोग नहीं कर सकते

डुडी यह केवल जेएस नहीं है। यह नोडज है। हम वर्कर-थ्रेड्स के साथ सीपीयू-बाउंड टास्क को ऑफलोड कर सकते हैं।

सबसे पहले हमें अपने कोर को nprocकमांड से चेक करना चाहिए

nproc

output
8

चलिए एक और JS फाइल बनाते हैं जैसे worker.js, नाम आप पर निर्भर है। इस फ़ाइल में, हम CPU-गहन कार्य करते हैं

//worker.js
const { parentPort } = require("worker_threads");

let counter = 0;
console.log("Worker started");
for (let i = 0; i < 15_000_000_000; i++) {
  counter++;
}

parentPort.postMessage(counter);

//app.js
const express = require("express");
const { Worker } = require("worker_threads");

const app = express();

app.get("/blocking-route", async (req, res) => {
  console.log("Blocking route called");
  let counter = 0;
  for (let i = 0; i < 15_000_000_000; i++) {
    counter++;
  }
  res.status(200).send(`result is ${counter}`);
});

app.get("/hello", (req, res) => {
  res.status(200).send(`Hello`);
});

app.get("/non-blocking-route", async (req, res) => {
  console.log("Non-blocking route called");
  const worker = new Worker("./worker.js");

  worker.on("message", (data) => {
    res.status(200).send(`result is ${data}`);
  });

  worker.on("error", (err) => {
    res.status(404).send(` error ${err}`);
  });

  console.log("I am not blocked");
});

app.listen(7333, () => console.log("Server started on port 7333"));

चलिए सर्वर शुरू करते हैं node app.js। अपना ब्राउज़र खोलें और http://localhost:7333/non-blocking-routeप्रतिक्रिया देने से पहले जाएं पर जाएं http://localhost:7333/hello। क्या आपको इसका एहसास हुआ? हमें तुरंत प्रतिक्रिया मिलती है। कोई रोक नहीं है। हमने लोडिंग समाप्त करने के लिए अन्य मार्गों की प्रतीक्षा नहीं की। क्योंकि सीपीयू-बाध्य कार्य लोड हो गया है और यह एक और धागा काम कर रहा है, और मुख्य धागा सभी अनुरोधों को संभालता है। हम अपने प्रदर्शन को बेहतर बनाने के लिए अधिक कर्मचारियों का उपयोग कर सकते हैं। उदाहरण के लिए, मेरे पास 8 कोर हैं और मैं अपनी प्रक्रिया को 8 में विभाजित कर सकता हूं।

निष्कर्ष

वर्कर (थ्रेड्स) सीपीयू-इंटेंसिव जावास्क्रिप्ट ऑपरेशंस में मदद कर सकते हैं। child_processया के विपरीत cluster, worker_threadsस्मृति साझा कर सकते हैं।

इस लेख में, मैंने इसे आसान बनाने और समझाने की कोशिश की है कि वर्कर_थ्रेड्स कैसे काम करता है?

पढ़ने के लिए धन्यवाद

> आरईएफ