NodeJs est-il monothread ?
Node.js exécute le code JavaScript dans un seul thread, ce qui signifie que votre code ne peut effectuer qu'une seule tâche à la fois. Mais Node.js lui-même est multithread et fournit des threads cachés via la bibliothèque `libuv`, qui gère les opérations d'E/S comme la lecture de fichiers à partir d'un disque ou les requêtes réseau. Grâce à l'utilisation de threads cachés, Node.js fournit des méthodes asynchrones qui permettent à votre code d'effectuer des requêtes d'E/S sans bloquer le thread principal.
Node.js nous a présenté le module worker-threads. Ce module permet de créer des threads et d'exécuter des tâches Javascript en parallèle. Si un thread termine une tâche, il envoie un message au thread principal qui contient le résultat afin que nous puissions l'utiliser dans le thread principal. Les threads de travail ne bloquent pas le thread principal, nous pouvons donc diviser et distribuer notre tâche à plusieurs pairs pour l'optimiser.
Prenons un exemple et regardons-le de plus près.
Nous créons un projet Nodejs et installons le framework Express
mkdir multiple-thread
cd multiple-thread
npm init -y
npm install express
Tout d'abord, il y a les processus et les threads. Nous devrions connaître les différences entre eux.
Qu'est-ce que le processus ?
Un processus exécute un programme dans le système d'exploitation. Il peut exécuter une tâche à la fois.
Regardons de plus près le processus de plus près. Créez un fichier JS et enregistrez le processus.
//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
Les threads sont un moyen relativement léger d'implémenter plusieurs chemins d'exécution dans une application. Au niveau du système, les programmes s'exécutent côte à côte, le système distribuant le temps d'exécution à chaque programme en fonction de ses besoins et des besoins des autres programmes.
Codons Express Server avec la route non bloquante et les routes bloquantes
Codons une route de blocage normale pour les utilisateurs. Dans 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'));
Il ne répond pas tant blocking-routequ'il n'a pas terminé et qu'il n'a pas renvoyé de réponse.
Pourquoi ne nous a-t-il pas répondu instantanément ?
Dans cet exemple, la boucle for liée au processeur bloque le thread principal. Tant que le thread principal est bloqué, Node.js ne peut traiter aucune requête tant que le processus lié au processeur n'est pas terminé. donc aucune des autres routes comme ne /hellofonctionne comme la /blocking-routeroute se charge.
Ainsi, si nous avons une API qui a des milliers de GETrequêtes simultanées vers la route non bloquante comme /hello, une seule requête vers /blocking-routebloquera toutes les routes de l'API. Cela signifie que toutes les routes d'application ne répondent pas.
DAAA IT's javascript, nous ne pouvons pas utiliser un autre fil
Dudeeee Ce n'est pas seulement JS. C'est Nodejs. Nous pouvons décharger une tâche liée au processeur avec des threads de travail.
Tout d'abord, nous devrions vérifier nos cœurs avec nprocla commande
nproc
output
8
Créons un autre fichier JS comme worker.js, le nom dépend de vous. Dans ce fichier, nous effectuons une tâche gourmande en 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"));
Démarrons le serveur avec node app.js. Ouvrez votre navigateur et allez http://localhost:7333/non-blocking-routeavant qu'il ne renvoie une réponse, allez à http://localhost:7333/hello. Vous en êtes-vous rendu compte ? Nous obtenons une réponse instantanément. Il n'y a pas de blocage. Nous n'avons pas attendu que les autres routes finissent de charger. Parce que la tâche liée au processeur est déchargée et qu'elle travaille sur un autre thread, et que le thread principal gère toutes les demandes. Nous pouvons utiliser plus de travailleurs pour améliorer nos performances. Par exemple, j'ai 8 cœurs et je peux diviser mon processus en 8.
Conclusion
Les travailleurs (threads) peuvent aider avec les opérations JavaScript gourmandes en CPU. Contrairement child_processà ou cluster, worker_threadspeut partager de la mémoire.
Dans cet article, j'ai essayé de le rendre plus facile et d'expliquer comment fonctionne worker_threads ?
Merci d'avoir lu
![Qu'est-ce qu'une liste liée, de toute façon? [Partie 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































