Maison >interface Web >js tutoriel >Améliorez les performances du serveur Node.js avec les threads de travail
Scénarios :
Avant de plonger dans les threads de travail, considérons quelques scénarios...
Supposons qu'un client télécharge un fichier volumineux sur un serveur qui doit être modifié ou implique le traitement de milliers de points de données en arrière-plan. Si le serveur attend la fin de cette tâche, le client reste en attente et ne peut pas explorer d'autres fonctionnalités. Imaginez si un client devait attendre 5 minutes sans pouvoir faire autre chose : ce serait frustrant et loin d'être convivial !
Considérez une autre situation dans laquelle vous téléchargez une image de profil et son traitement, sa conversion et son stockage dans la base de données prennent beaucoup de temps. Pendant ce temps, si le serveur vous empêche d'effectuer d'autres tâches, cela réduit considérablement l'expérience utilisateur.
Dans le premier cas, ne serait-il pas préférable que le serveur vous permette d'explorer d'autres fonctionnalités pendant que le fichier est encore en cours de traitement ? De cette façon, vous n'aurez pas à attendre (puisque le serveur ne vous bloquera pas), ce qui entraînera une expérience plus fluide.
Dans le deuxième cas, que se passe-t-il si le traitement de l'image se fait en arrière-plan, vous permettant de continuer à utiliser d'autres fonctionnalités sans attendre ?
Solution :
Alors, quel est le moyen efficace d'optimiser les performances du système dans ces scénarios ? Bien qu'il existe plusieurs approches, l'utilisation de threads de travail constitue une excellente solution. Les threads de travail ont été introduits dans la version 10 de Node.js et sont particulièrement utiles pour effectuer des tâches gourmandes en CPU en parallèle, réduisant ainsi la charge sur le CPU principal.
Les threads de travail fonctionnent en arrière-plan, créant un thread distinct qui gère les calculs intensifs sans bloquer le thread principal, permettant ainsi au serveur de rester réactif pour d'autres tâches. Alors que JavaScript est traditionnellement un langage monothread et que Node.js fonctionne dans un environnement monothread, les threads de travail permettent le multithread en répartissant les opérations sur plusieurs threads. Cette exécution parallèle optimise l'utilisation des ressources et réduit considérablement le temps de traitement.
Aujourd'hui, nous allons implémenter une simple application nodejs avec le package par défaut worker_threads . Créez d’abord un serveur express sur lequel une simple requête get s’exécute.
Initialisez d'abord le projet :
$ npm init -y
Installez le module express et nodemon :
$ npm j'exprime nodemon
Création d'un serveur nodejs simple qui s'exécute sur le port 3000.
Import express from ‘express’; const app = express(); const port = 3000; // Basic endpoint to test server app.get(‘/’, (req, res) => { res.send(‘Hello World!’); }); app.listen(port, () => console.log(`Server running on port ${port}`));
Ici, nous avons créé un serveur qui fonctionnera sur le port 3000.
Pour exécuter, modifions notre fichier package.json.
Ajoutez le type en tant que module comme ci-dessous pour obtenir les modules ES6. Modifiez également sous la partie scripts comme ci-dessous.
{ "name": "worker_express", "version": "1.0.0", "description": "", "main": "index.js", "type": "module", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node index.js", "dev": "nodemon index.js" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "dotenv": "^16.4.5", "express": "^4.19.2", "nodemon": "^3.1.4" } }
Exécutons maintenant notre application en mode développement avec nodemon :
$ npm exécuter le développement
Vous verrez le message Serveur exécuté sur le port 3000. Allez maintenant sur localhost:3000 et vous pourrez voir le message Hello World ! Pour l'instant, nous n'avons fait qu'un simple serveur nodejs express.
Créons maintenant un autre fichier nommé service.js
Ici, nous pouvons créer une fonction de séquence de Fibonacci qui trouve la séquence de Fibonacci du nième nombre.
// service.js function fibonacci(n) { if (n <= 1) return 1; return fibonacci(n-1) + fibonacci(n-2); } export default fibonacci;
Ajoutons maintenant un autre point de terminaison de l'API au fichier index.js et appelons la fonction fibonacci à partir du fichier service.js. Nous calculerons le 40ème nombre de Fibonacci à titre d'exemple.
import fibonacci from "./service.js"; // Fibonacci endpoint app.get('/fibonacci', (req, res) => { fibonacci(40) res.send('fibonacci called'); })
Si vous cliquez sur l'URL http://localhost:3000/fibonacci, vous verrez que cela tarde un peu, vous faisant attendre. Le temps de retard dépend du calcul.
Vous pouvez réessayer en commentant la fonction et voir que cela prend moins de temps, soit environ une milliseconde.
Dans ce cas, vous devrez peut-être effectuer d'autres opérations lourdes qui prennent du temps et réduisent les performances.
Dans ce cas, nous pouvons utiliser le module worker_threads, qui est disponible par défaut dans Node.js depuis la version 10. Modifions maintenant le code pour appliquer worker_threads et voir l'effet.
Importez Worker depuis worker_thread qui est le package par défaut de node js.
import { Worker } from "worker_threads";
Modifiez maintenant le point de terminaison de l'API comme ci-dessous.
// Endpoint using worker thread for CPU-intensive task app.get('/fibonacci', (req, res) => { const worker = new Worker('./service.js', {workerData: 40}); // Handle messages from worker thread worker.on('message', (resolve) => console.log(resolve)); res.send('fibonacci called'); })
Ici, nous créons une instance de travailleur et définissons le nom de fichier service.js comme premier argument, tandis que le deuxième argument transmet les paramètres via WorkerData. Vous pouvez remplacer le paramètre workerData par n'importe quelle autre donnée au lieu de 40.
worker.on(‘message’, ….) This sets up an event listener on the worker for the ‘message’ event. The message event is emitted by the worker when it sends data back to the main thread using parentrPort.postMessage(...).
(resolve) => console.log(resolve) this is a callback function that will be executed when the worker sends back the data after operation. The received message(data) is passed to this function as the resolve parameter.
Now let’s update our service.js file.
import { workerData, parentPort } from 'worker_threads'; // Function to compute Fibonacci sequence function fibonacci(n) { if (n <= 1) return 1; return fibonacci(n-1) + fibonacci(n-2); } // Compute Fibonacci using workerData const fibonacciAt = fibonacci(workerData); // Send result back to the main thread parentPort.postMessage(fibonacciAt);
Here, we import workerData and parentPort, which allow us to receive the data sent through workerData and return the result via the postMessage method of parentPort, both imported from worker_threads.
Test the Setup:
Now, send a request to http://localhost:3000/fibonacci and notice that the server no longer blocks the main thread. The time-consuming operation occurs in the background on a separate thread, significantly reducing the response time and improving user experience.
Here is the source code in github.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!