Eine kurze Diskussion zum Erstellen eines Clusters in nodejs

Eine kurze Diskussion zum Erstellen eines Clusters in nodejs

Cluster-Cluster

Wir wissen, dass der Ereignisschleifen- oder Ereignisantwortprozessor von nodejs ein Single-Thread ist, aber heutzutage sind CPUs grundsätzlich Multi-Core. Um die Multi-Core-Eigenschaften moderner CPUs voll auszunutzen, können wir einen Cluster erstellen, sodass mehrere untergeordnete Prozesse denselben Server-Port gemeinsam nutzen können.

Das heißt, durch einen Cluster können wir mehrere untergeordnete Prozesse verwenden, um Anfragen für denselben Port zu bedienen.

Schauen wir uns ein einfaches Beispiel für die Verwendung eines Clusters in einem HTTP-Server an:

const cluster = erfordern('cluster');
const http = erfordern('http');
const numCPUs = require('os').cpus().length;

wenn (cluster.isMaster) {
  console.log(`Der Hauptprozess ${process.pid} läuft`);

  // Einen Arbeitsprozess erzeugen.
  für (lass i = 0; i < Anzahl CPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (Arbeiter, Code, Signal) => {
    console.log(`Der Arbeitsprozess ${worker.process.pid} wurde beendet`);
  });
} anders {
  // Arbeitsprozesse können jede TCP-Verbindung gemeinsam nutzen.
  // In diesem Beispiel wird der HTTP-Server gemeinsam genutzt.
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Hallo Welt\n');
  }).listen(8000);

  console.log(`Arbeitsprozess ${process.pid} gestartet`);
}

Clusterdetails

Das Clustermodul ist von lib/cluster.js abgeleitet. Wir können cluster.fork() verwenden, um einen untergeordneten Arbeitsprozess zu erstellen, der Anfragen vom Hauptprozess verarbeitet.

Ereignisse in einem Cluster

Der Cluster erbt von events.EventEmitter, sodass der Cluster Ereignisse senden und empfangen kann.

Der Cluster unterstützt 7 Ereignisse: Trennen, Beenden, Fork, Listening, Nachricht, Online und Setup.

Bevor wir die Trennung erklären, stellen wir zunächst ein Konzept namens IPC vor. Der vollständige Name von IPC lautet Inter-Process Communication, was Interprozesskommunikation bedeutet.

IPC wird hauptsächlich für die Kommunikation zwischen dem Hauptprozess und dem Unterprozess verwendet. Ein Worker-Prozess stellt nach seiner Erstellung automatisch eine Verbindung zu seinem Master-Prozess her. Die Verbindung wird getrennt, wenn das Ereignis „Disconnect“ ausgelöst wird.

Es gibt viele Gründe für das Auslösen des Trennungsereignisses. Dies kann ein aktiver Aufruf von worker.disconnect() oder das Beenden bzw. Abbrechen des Arbeitsprozesses sein.

cluster.on('Trennen', (Arbeiter) => {
  console.log(`Die Verbindung zum Arbeitsprozess #${worker.id} wurde getrennt`);
});

Das Exit-Ereignis wird ausgelöst, wenn ein beliebiger Arbeitsprozess geschlossen wird. Es wird im Allgemeinen verwendet, um zu überwachen, ob ein Prozess im Cluster abnormal beendet wird. Wenn er beendet wird, erstellen Sie mit cluster.fork einen neuen Prozess, um sicherzustellen, dass genügend Prozesse zur Bearbeitung der Anforderungen vorhanden sind.

cluster.on('exit', (Arbeiter, Code, Signal) => {
  console.log('Arbeitsprozess %d geschlossen (%s). Neustart...',
              worker.process.pid, Signal || Code);
  cluster.fork();
});

Das Fork-Ereignis wird ausgelöst, wenn die Methode cluster.fork aufgerufen wird.

const-Timeouts = [];
Funktion errorMsg() {
  console.error('Verbindungsfehler');
}

cluster.on('fork', (Arbeiter) => {
  Timeouts[Arbeitskraft.ID] = setzeTimeout(Fehlermeldung, 2000);
});

Die Abhörereignisse des Hauptprozesses und des Arbeitsprozesses werden ausgelöst, wenn der Arbeitsprozess die Abhörmethode aufruft.

cluster.on('listening', (Arbeiter, Adresse) => {
  konsole.log(
    `Arbeitsprozess verbunden mit ${address.address}:${address.port}`);
});

Der Worker stellt den Arbeitsthread dar und die Adresse enthält drei Attribute: Adresse, Port und Adresstyp. Der Adresstyp hat vier optionale Werte:

  • 4 (TCPv4)
  • 6 (TCPv6)
  • -1 (Unix-Domänen-Socket)
  • „udp4“ oder „udp6“ (UDP v4 oder v6)

Das Nachrichtenereignis wird ausgelöst, wenn der Hauptprozess eine vom untergeordneten Prozess gesendete Nachricht empfängt.

Wenn der Hauptprozess einen Arbeitsprozess generiert, wird „Fork“ ausgelöst, und wenn der Arbeitsprozess ausgeführt wird, wird „Online“ ausgelöst.

Wenn die Methode setupMaster aufgerufen wird, wird das Setup-Ereignis ausgelöst.

Methoden im Cluster

Es gibt drei Methoden im Cluster, nämlich Disconnect, Fork und SetupMaster.

cluster.disconnect([Rückruf])

Durch den Aufruf der Disconnect-Methode des Clusters wird tatsächlich die Disconnect-Methode in jedem Worker im Cluster aufgerufen. Dadurch wird der Worker vom Hauptprozess getrennt.

Wenn die Verbindung aller Worker getrennt ist, wird der Rückruf ausgeführt.

cluster.fork([Umgebung])

Die Fork-Methode erstellt aus dem Hauptprozess einen neuen untergeordneten Prozess. Wobei env das Schlüssel-Wert-Paar ist, das den Prozessumgebungsvariablen hinzugefügt werden soll.

fork gibt ein cluster.Worker-Objekt zurück, das den Arbeitsprozess darstellt.

Die letzte Methode ist setupMaster:

cluster.setupMaster([Einstellungen])

Standardmäßig erstellt der Cluster untergeordnete Prozesse über die Fork-Methode, aber wir können dieses Verhalten über SetupMaster ändern. Durch Festlegen der Einstellungsvariable können wir das Verhalten des nachfolgenden Fork-Unterprozesses ändern.

Schauen wir uns ein Beispiel für SetupMaster an:

const cluster = erfordern('cluster');
cluster.setupMaster({
  exec: "worker.js",
  Argumente: ['--use', 'https'],
  still: wahr
});
cluster.fork(); // https-Arbeitsprozess cluster.setupMaster({
  exec: "worker.js",
  Argumente: ['--use', 'http']
});
cluster.fork(); // HTTP-Arbeitsprozess

Attribute im Cluster

Über das Clusterobjekt können wir mithilfe von isMaster und isWorker feststellen, ob es sich bei dem Prozess um den Hauptprozess handelt.

Sie können über „worker“ einen Verweis auf das aktuelle Worker-Prozessobjekt erhalten:

const cluster = erfordern('cluster');

wenn (cluster.isMaster) {
  console.log('Dies ist der Hauptprozess');
  cluster.fork();
  cluster.fork();
} sonst wenn (cluster.isWorker) {
  console.log(`Dies ist der Arbeitsprozess#${cluster.worker.id}`);
}

Sie können die aktiven Worker-Prozessobjekte über Worker durchlaufen:

// Über alle Arbeitsprozesse iterieren.
Funktion eachWorker(Rückruf) {
  für (const id in cluster.workers) {
    Rückruf (Cluster.Workers[ID]);
  }
}
jederArbeiter((Arbeiter) => {
  worker.send('alle Arbeitsprozesse benachrichtigen');
});

Jeder Arbeiter hat eine ID-Nummer, die zur Lokalisierung des Arbeiters dient.

Arbeiter in einem Cluster

Die Worker-Klasse enthält alle allgemeinen Informationen und Methoden zum Worker-Prozess. Was cluster.fork erzeugt, ist das Worker-Objekt.

Worker-Ereignisse sind Cluster-Ereignissen sehr ähnlich und unterstützen sechs Ereignisse: Trennen, Fehler, Beenden, Zuhören, Nachricht und Online.

Der Worker enthält drei Eigenschaften: ID, Prozess und exitedAfterDisconnect.

Die ID ist die eindeutige Kennung des Mitarbeiters.

Der Prozess im Worker ist tatsächlich ein ChildProcess-Objekt, das über child_process.fork() erstellt wird.

Da der Prozess eine globale Variable im Worker ist, können wir den Prozess direkt im Worker verwenden, um Nachrichten zu senden.

exitedAfterDisconnect bedeutet, dass der Wert „true“ ist, wenn der Arbeitsprozess aufgrund von .kill() oder .disconnect() beendet wird. Erfolgt der Ausstieg auf andere Weise, ist der Rückgabewert „false“. Undefiniert, wenn der Arbeitsprozess noch nicht beendet wurde.

Wir können worker.exitedAfterDisconnect verwenden, um zu unterscheiden, ob es sich um einen aktiven oder passiven Exit handelt. Der Hauptprozess kann anhand dieses Werts entscheiden, ob der Worker-Prozess neu generiert werden soll.

cluster.on('exit', (Arbeiter, Code, Signal) => {
  wenn (worker.exitedAfterDisconnect === true) {
    console.log('Das ist ein spontaner Ausstieg, kein Grund zur Sorge');
  }
});

// Beenden Sie den Arbeitsprozess.
Arbeiter.töten();

Der Worker unterstützt außerdem 6 Methoden: Senden, Töten, Zerstören, Trennen, isConnected und isDead.

Hier erklären wir hauptsächlich die Sendemethode zum Senden von Nachrichten:

worker.send(Nachricht[, sendHandle[, Optionen]][, Rückruf])

Sie können sehen, dass die Sendemethode und die Sendemethodenparameter im child_process tatsächlich sehr ähnlich sind. Im Wesentlichen befindet sich worker.send im Masterprozess, der eine Nachricht an einen bestimmten Workerprozess sendet. Entspricht ChildProcess.send(). Im Worker-Prozess wird dadurch eine Nachricht an den Master-Prozess gesendet. Entspricht process.send().

wenn (cluster.isMaster) {
  const worker = cluster.fork();
  arbeiter.send('hallo');

} sonst wenn (cluster.isWorker) {
  process.on('Nachricht', (msg) => {
    verarbeiten.senden(Nachricht);
  });
}

Wenn wir uns im obigen Beispiel im Hauptprozess befinden, können wir worker.send zum Senden von Nachrichten verwenden. Im untergeordneten Prozess können Sie die globale Variable process im Worker verwenden, um Nachrichten zu senden.

Zusammenfassen

Durch die Verwendung eines Clusters können die Vorteile einer Multi-Core-CPU voll ausgeschöpft werden. Ich hoffe, Sie können es in tatsächlichen Projekten anwenden.

Oben finden Sie eine kurze Erläuterung der Details zum Erstellen eines Clusters in nodejs. Weitere Informationen zum Erstellen eines Clusters in nodejs finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • So teilen Sie Daten zwischen mehreren Prozessen im Clustermodul in Nodejs
  • Prinzip des Redis Cluster-Daten-Sharding-Mechanismus
  • Redis Cluster-Grafiken
  • Einführung in den Redis-Cluster
  • Detaillierte Interpretation des Clustermoduls in Node.js
  • Eine kurze Diskussion über Cluster in Knoten
  • Tutorial zur Verwendung von Clustern in node.js
  • Node.js verwendet Cluster zur Implementierung mehrerer Prozesse

<<:  Analyse, wie eine gespeicherte Prozedur in MySQL erstellt wird, um einer Datentabelle neue Felder hinzuzufügen

>>:  Diagramm des Hyperledger Fabric 1.4-Umgebungskonstruktionsprozesses unter Windows 10

Artikel empfehlen

CentOS7 64-Bit-Installation MySQL Grafik-Tutorial

Voraussetzungen für die Installation von MySQL: I...

Einfache und schnelle Einführung in die React-Routing-Entwicklung

Installieren Geben Sie zur Installation den folge...

Einführung in die Vue3 Composition API

Inhaltsverzeichnis Überblick Beispiel Warum wird ...

Mehrere Möglichkeiten zur Lösung von CSS-Stilkonflikten (Zusammenfassung)

1. Verfeinern Sie den Selektor Durch die Verwendu...

Detaillierte Erklärung redundanter und doppelter Indizes in MySQL

MySQL ermöglicht das Erstellen mehrerer Indizes f...

Der Implementierungsprozess der Linux-Prozessnetzwerkverkehrsstatistik

Vorwort Linux verfügt über entsprechende Open-Sou...

Natives JS zur Implementierung der E-Mail-Eingabeaufforderung im Anmeldefeld

Dieser Artikel beschreibt eine native JS-Implemen...

Eine kurze Diskussion über den virtuellen Speicher von Linux

Inhaltsverzeichnis Herkunft Virtueller Speicher P...

Verwendung des Linux-Befehls ifconfig

1. Befehlseinführung Der Befehl ifconfig (Netzwer...

Lösen Sie das Problem der Angabe der UDP-Portnummer im Docker

Wenn Docker einen Container startet, gibt es den ...