Module worker_threads de Node.js

Java FileModules intégrés de Node.js


de Node.jsworker_threadsLe module permet aux développeurs de créer plusieurs threads dans les applications Node.js. Contrairement au modèle Node.js traditionnel monothread, ce module vous permet d’exécuter du code JavaScript dans des threads séparés, ce qui permet un véritable traitement parallèle.

Pourquoi le multithreading est nécessaire

Node.js est monothread par défaut, ce qui signifie :

  1. Les tâches gourmandes en CPU bloqueront la boucle d’événements
  2. Impossible d’exploiter pleinement les performances des processeurs multicœurs
  3. Les calculs de longue durée réduiront la réactivité de l’application

worker_threadsLe module résout ces problèmes, vous permettant de décharger les tâches gourmandes en CPU vers d’autres threads.


Concepts de base

Thread principal vs thread de travail

  1. Thread principal: thread d’exécution principal de l’application, responsable de la création et de la gestion des threads de travail.
  2. Thread de travail: thread d’exécution indépendant créé par le thread principal, utilisé pour exécuter des tâches spécifiques.

Communication entre threads

Les threads de travail et le thread principal communiquent par passage de messages plutôt que par mémoire partagée. Cette approche évite les problèmes complexes de synchronisation.


API principale

Principaux composants du module worker_threads

Exemple

const {
  Worker,          // Classe utilisée pour créer de nouveaux threads
  isMainThread,    // Détermine si le contexte actuel est le thread principal
  parentPort,      // Utilisé pour communiquer avec le thread parent
  workerData       // Données transmises lors de la création du thread
} = require('worker_threads');

Exemple d'utilisation

Créer un thread worker simple

Code du thread principal (main.js):

Exemple

const { Worker, isMainThread } = require('worker_threads');

if (isMainThread) {
  // Code du thread principal
  console.log('This is the main thread');
 
  // Créer un thread worker
  const worker = new Worker('./worker.js', {
    workerData: {
      message: 'Bonjour, thread de travail !'
    }
  });
 
  // Écouter les messages provenant du thread de travail
  worker.on('message', (msg) => {
    console.log(`Reçu du thread de travail: ${msg}`);
  });
 
  worker.on('error', (err) => {
    console.error('Erreur du thread de travail :', err);
  });
 
  worker.on('exit', (code) => {
    if (code !== 0) {
      console.error(`Le thread de travail s'est terminé de façon inattendue, code de sortie: ${code}`);
    }
  });
} else {
  // Code du thread de travail
  require('./worker.js');
}

Code du thread de travail (worker.js):

Exemple

const { parentPort, workerData } = require('worker_threads');

console.log('Ceci est le thread worker');
console.log('Message reçu du thread principal :', workerData.message);

// Simuler un peu de travail
setTimeout(() => {
  // Envoyer un message au thread principal
  parentPort.postMessage('Travail terminé !');
}, 2000);

Utilisation avancée

Passer des données complexes

Exemple

// Thread principal
const worker = new Worker('./worker.js', {
  workerData: {
    array: new Uint8Array([1, 2, 3, 4]),
    object: { key: 'value' }
  }
});

// Thread worker
console.log(workerData.array);  // Uint8Array [ 1, 2, 3, 4 ]
console.log(workerData.object); // { key: 'value' }

Mémoire partagée (SharedArrayBuffer)

Exemple

// Thread principal
const sharedBuffer = new SharedArrayBuffer(16);
const arr = new Uint8Array(sharedBuffer);
arr[0] = 1;

const worker = new Worker('./worker.js', {
  workerData: { sharedBuffer }
});

// Thread worker
const { sharedBuffer } = workerData;
const arr = new Uint8Array(sharedBuffer);
console.log(arr[0]); // 1

Bonnes pratiques

  1. Utilisation raisonnable: Ne créez pas un thread pour chaque petite tâche ; la création de threads a un surcoût.
  2. Gestion des erreurs: Écoutez toujours les événements 'error' et 'exit' des worker threads.
  3. Nettoyage des ressources: Assurez-vous que les worker threads se terminent correctement après avoir terminé leurs tâches.
  4. Optimisation de la communication: Minimisez la quantité de données transmises dans la communication entre threads.
  5. Affinité CPU: Pour les threads de longue durée, envisagez de définir l'affinité CPU.

Considérations de performance

  1. Pool de threads: Pour les tâches fréquentes de courte durée, envisagez d'utiliser un modèle de pool de threads.
  2. Équilibrage de charge: Répartissez uniformément les threads de travail sur les systèmes multicœurs.
  3. Utilisation de la mémoire: Chaque thread de travail dispose de sa propre instance V8 et de son propre espace mémoire.

Questions courantes

Quand faut-il utiliser worker_threads ?

  • Calculs intensifs en CPU
  • Besoin de traiter plusieurs tâches en parallèle
  • Besoin d'utiliser des CPU multicœurs

Quelle est la différence entre worker_threads et le module cluster ?

  • clusterCrée plusieurs processus Node.js
  • worker_threadsCrée des threads qui partagent le même processus

Comment déboguer les threads de travail ?

Utiliser--inspectet--inspect-brkoption, et attribuez un port de débogage différent à chaque thread de travail.

Exemple

node --inspect=9229 main.js

Résumé

de Node.jsworker_threadsmodule apporte de véritables capacités de multi-threading à JavaScript, permettant aux développeurs de mieux exploiter les performances des CPU multicœurs modernes. En utilisant correctement les worker threads, vous pouvez considérablement améliorer les performances des applications gourmandes en CPU tout en conservant les avantages des E/S non bloquantes de Node.js.

Java FileModules intégrés de Node.js

Autres extensions