Lassen Sie uns im Detail darüber sprechen, wie der NodeJS-Prozess beendet wird

Lassen Sie uns im Detail darüber sprechen, wie der NodeJS-Prozess beendet wird

Vorwort

Es gibt mehrere Gründe, die dazu führen können, dass ein NodeJS-Prozess beendet wird. Einige dieser Faktoren sind vermeidbar, z. B. wenn Ihr Code eine Ausnahme auslöst, und andere sind unvermeidbar, z. B. wenn nicht genügend Arbeitsspeicher vorhanden ist. Der globale Variablenprozess ist eine Event Emitter-Instanz. Wenn der Prozess ordnungsgemäß beendet wird, löst der Prozess ein Exit-Ereignis aus. Der Anwendungscode kann auf dieses Ereignis hören, um eine endgültige Bereinigung durchzuführen.

In der folgenden Tabelle sind die Faktoren aufgeführt, die zum Beenden eines Prozesses führen können.

arbeiten Beispiel
Manuelles Beenden prozess.exit(1)
Nicht abgefangene Ausnahme throw new Error()
Unbehandelte Ablehnung eines Versprechens Versprechen.ablehnen()
Nicht behandeltes Fehlerereignis EventEmitter#emit('Fehler')
Unbearbeitetes Signal kill <PROZESS_ID>

Aktiver Rückzug

process.exit(code) ist der direkteste Weg, einen Prozess zu beenden. Der Codeparameter ist optional und kann eine beliebige Zahl zwischen 0 und 255 sein. Der Standardwert ist 0. 0 gibt an, dass der Prozess erfolgreich ausgeführt wurde, und eine Zahl ungleich Null gibt an, dass der Prozess fehlgeschlagen ist.

Wenn process.exit() verwendet wird, erfolgt keine Ausgabe an die Konsole. Wenn wir beim Beenden des Prozesses Fehlerinformationen an die Konsole ausgeben möchten, müssen wir die Fehlerinformationen vor dem Aufruf anzeigen.

Knoten -e "Prozess.exit(42)"
echo $?

Der obige Code beendet den NodeJS-Prozess direkt und es gibt keine Ausgabeinformationen in der Befehlszeile. Wenn ein Prozess beendet wird, können Benutzer keine effektiven Fehlerinformationen erhalten.

Funktion checkConfig(config) {
  wenn (!config.host) {
    console.error("In der Konfiguration fehlt der Parameter 'host'!");
    prozess.exit(1);
  }
}

Im obigen Code drucken wir eine eindeutige Fehlermeldung, bevor der Prozess beendet wird.

process.exit() ist sehr leistungsfähig, sollte aber nicht in einer Dienstprogrammbibliothek verwendet werden. Wenn in der Tool-Bibliothek ein Fehler auftritt, sollten wir ihn als Ausnahme auslösen und den Anwendungscode entscheiden lassen, wie der Fehler behandelt wird.

Ausnahmen, Ablehnungen und ausgegebene Fehler

process.exit() ist in Szenarien wie der Überprüfung der Konfiguration beim Anwendungsstart sehr nützlich, ist jedoch nicht für die Behandlung von Laufzeitausnahmen geeignet und wir benötigen andere Tools.

Wenn eine Anwendung beispielsweise eine HTTP-Anforderung verarbeitet, sollte ein Fehler nicht dazu führen, dass der Prozess beendet wird. Stattdessen sollten wir eine Antwort mit einer Fehlermeldung zurückgeben.

Die Fehlerklasse kann Daten enthalten, die die Details des aufgetretenen Fehlers beschreiben, beispielsweise den Aufrufstapel und den Fehlertext. Normalerweise definieren wir XXXError für bestimmte Szenarien, und diese XXXErrors erben alle die Error-Klasse.

Wenn wir das Schlüsselwort „throw“ verwenden oder wenn ein Fehler in der Codelogik vorliegt, wird ein Fehler ausgelöst. An diesem Punkt wird der Systemaufrufstapel abgewickelt und jede Funktion verlassen, bis eine Try/Catch-Anweisung gefunden wird, die den aktuellen Aufruf umschließt. Wenn keine Try/Catch-Anweisung vorhanden ist, wird der Fehler als nicht abgefangene Ausnahme betrachtet.

Normalerweise definieren wir in NodeJS-Anwendungen eine Codeeigenschaft für die Error-Klasse als Fehlercode, um den spezifischen Fehler zu beschreiben. Der Vorteil dabei ist, dass der Fehlercode eindeutig und lesbar gehalten werden kann. Gleichzeitig können wir auch das Nachrichtenattribut verwenden, um die spezifischen Fehlerinformationen zu beschreiben.

Wenn eine nicht abgefangene Ausnahme ausgelöst wird, wird der Aufrufstapel auf der Konsole ausgegeben und der Prozess mit dem Beendigungsstatus 1 beendet.

/tmp/foo.js:1
throw new TypeError('ungültiges foo');
^
Fehler: ungültiges foo
    bei Objekt.<anonym> (/tmp/foo.js:2:11)
    ... ABGESCHNITTEN ...
    bei internal/main/run_main_module.js:17:47

Diese Konsolenausgabe zeigt, dass der Fehler in Zeile 2, Spalte 11 in foo.js aufgetreten ist.

Der globale Variablenprozess ist eine Ereignisemitterinstanz, die diese nicht abgefangenen Ausnahmen verarbeiten kann, indem sie auf das Ereignis „uncaughtException“ achtet. Der folgende Code zeigt, wie man es verwendet:

const logger = require("./lib/logger.js");
process.on("uncaughtException", (Fehler) => {
  logger.send("Eine nicht abgefangene Ausnahme ist aufgetreten", error, () => {
    konsole.fehler(fehler);
    prozess.exit(1);
  });
});

Die Ablehnung eines Versprechens ähnelt dem Auslösen einer Ausnahme. Wir können dafür sorgen, dass ein Versprechen den Status „Abgelehnt“ erreicht, indem wir die Funktion „reject()“ aufrufen oder in einer asynchronen Funktion eine Ausnahme auslösen. Die folgenden beiden Codeausschnitte haben ähnliche Funktionen.

Promise.reject(neuer Fehler("oh nein"));

(asynchron () => {
  wirf einen neuen Fehler („oh nein“);
})();

Derzeit führt die Ablehnung eines Promise in NodeJS 14 nicht dazu, dass der Prozess beendet wird. In nachfolgenden Versionen kann die Ablehnung eines Promise dazu führen, dass der Prozess beendet wird.

Hier sehen Sie einige Beispiele für die Konsolenausgabe einer nicht abgefangenen Promise-Ablehnung.

(Knoten: 52298) UnhandledPromiseRejectionWarning: Fehler: oh nein
bei Objekt.<anonymous> (/tmp/reject.js:1:16)
... ABGESCHNITTEN ...
bei internal/main/run_main_module.js:17:47
(Knoten: 52298) UnhandledPromiseRejectionWarning: Nicht behandeltes Versprechen
Dieser Fehler entstand entweder durch das Werfen innerhalb eines
asynchrone Funktion ohne Catch-Block oder durch Ablehnung eines Promises
was nicht mit .catch() behandelt wurde.

Wir können nicht abgefangene Ablehnungen behandeln, indem wir auf das Ereignis „unhandledRejection“ hören. Der Beispielcode lautet wie folgt:

Prozess.on("unbehandelte Ablehnung", (Grund, Versprechen) => {});

Event Emitter ist ein Basismodul in NodeJS und wird häufig verwendet. Wenn das Fehlerereignis des Ereignisemitters nicht behandelt wird, gibt der Ereignisemitter einen Fehler aus und führt zum Beenden des Prozesses. Unten sehen Sie die Konsolenausgabe eines Event Emitter-Fehlers.

Ereignisse.js:306
throw err; // Nicht behandeltes „Fehler“-Ereignis
^
Fehler [ERR_UNHANDLED_ERROR]: Unbehandelter Fehler. (undefiniert)
bei EventEmitter.emit (events.js:304:17)
bei Objekt.<anonym> (/tmp/foo.js:1:40)
... ABGESCHNITTEN ...
bei internal/main/run_main_module.js:17:47 {
Code: 'ERR_UNHANDLED_ERROR',
Kontext: undefiniert
}

Wenn wir den Ereignisemitter verwenden, müssen wir daher sicherstellen, dass wir auf das Fehlerereignis achten, damit die Anwendung bei auftretenden Fehlern diese Fehler verarbeiten und Abstürze vermeiden kann.

Signal

Signale sind Betriebsmeldungen, die einen Mechanismus zur Kommunikation zwischen Prozessen bereitstellen. Ein Signal ist normalerweise eine Zahl, kann aber auch durch eine Zeichenfolge identifiziert werden. Beispielsweise identifiziert SIGKILL die Zahl 9. Verschiedene Betriebssysteme definieren Signale unterschiedlich. In der folgenden Tabelle sind die grundlegenden, gängigen Signaldefinitionen aufgeführt.

Name Nummer Ist es verarbeitbar? NodeJS-Standardverhalten Was das Signal bedeutet
ANMELDEN 1 Ja aufhören Die übergeordnete Befehlszeile ist geschlossen
ZEICHEN 2 Ja aufhören Versuchen Sie, von der Befehlszeile aus zu unterbrechen, z. B. mit Strg+C
SIGQUIT 3 Ja aufhören Versuchen Sie, die Befehlszeile durch Drücken von Strg + Z zu verlassen
SIGKILL 9 NEIN aufhören Beenden eines Prozesses erzwingen
SIGUSR1 10 Ja Starten des Debuggers Benutzerdefiniertes Signal
SIGUSR2 12 Ja aufhören Benutzerdefiniertes Signal
SIGTERM 15 Ja aufhören Der Prozess wird ordnungsgemäß beendet
SIGSTOP 19 NEIN aufhören Der Prozess wurde gewaltsam gestoppt

Die Verarbeitbarkeit des Signals in dieser Tabelle gibt an, ob das Signal vom Prozess empfangen und verarbeitet werden kann. Das NodeJS-Standardverhalten gibt die Standardaktion an, die der Prozess nach Erhalt dieses Signals ausführt.

Wir können diese Signale auf folgende Weise überwachen.

#!/usr/bin/env Knoten
console.log(`Prozess-ID: ${process.pid}`);
process.on("SIGHUP", () => console.log("Empfangen: SIGHUP"));
process.on("SIGINT", () => console.log("Empfangen: SIGINT"));
setTimeout(() => {}, 5 * 60 * 1000); // Prozess am Leben halten

Führen Sie diesen Code in einem Befehlszeilenfenster aus und drücken Sie Strg + C. Der Vorgang wird nicht beendet. Stattdessen wird in der Konsole eine Zeile mit Protokollinformationen ausgegeben, die angibt, dass ein SIGINT-Signal empfangen wurde. Öffnen Sie ein neues Befehlszeilenfenster und führen Sie den folgenden Befehl aus. PROCESS_ID ist die vom obigen Programm ausgegebene Prozess-ID.

kill -s SIGHUP <PROZESS_ID>

Über die neue Befehlszeile haben wir ein SIGHUP-Signal an den ursprünglichen Programmprozess gesendet und eine Zeile mit Protokollinformationen, die angibt, dass das SIGHUP-Signal empfangen wurde, wird im ursprünglichen Befehlszeilenfenster gedruckt.

Im NodeJS-Code können Prozesse auch Signale an andere Prozesse senden. Zum Beispiel:

Knoten -e "Prozess.kill(<PROZESS_ID>, 'SIGHUP')"

Dieser Code gibt außerdem im ersten Befehlszeilenfenster eine Protokollzeile aus, die angibt, dass ein SIGHUP-Signal empfangen wurde.

Wenn wir den Prozess des ersten Kommandozeilenfensters beenden möchten, können wir dies mit folgendem Befehl tun.

kill -9 <PROZESS_ID>

In NodeJS werden häufig Signale verwendet, um den ordnungsgemäßen Abschluss des Prozesses zu steuern. Wenn beispielsweise in Kubernetes ein Pod beendet werden soll, sendet k8s ein SIGTERM-Signal an den Prozess im Pod und startet einen 30-Sekunden-Timer. Die Anwendung hat 30 Sekunden Zeit, um die Verbindung zu schließen, Daten zu speichern usw. Wenn der Prozess nach 30 Sekunden noch aktiv ist, sendet k8s ein weiteres SIGKILL, um die Schließung des Prozesses zu erzwingen.

Zusammenfassung

In diesem Artikel werden mehrere Faktoren beschrieben, die zum Beenden eines Prozesses führen können:

  • Aktiver Rückzug
  • Nicht abgefangene Ausnahme, nicht behandelte Ablehnung eines Versprechens, nicht behandelte Event Emitter-Fehlerereignisse
  • Systemsignal

Dies ist das Ende dieses Artikels zum Beenden des NodeJS-Prozesses. Weitere Informationen zum Beenden des NodeJS-Prozesses finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Tiefgreifendes Verständnis des Node.js-Prozessexits

<<:  Tutorial zur Installation der DAMO-Datenbank auf Centos7

>>:  So implementieren Sie Lastenausgleich in MySQL

Artikel empfehlen

Detaillierte Erklärung der Schritte zum Erstellen eines Webservers mit node.js

Vorwort Es ist sehr einfach, einen Server in node...

Grafisches Tutorial zur kostenlosen Installationsversion von MySQL 5.7.17 winx64

Aktuelle Erfahrungen mit der Installation der kos...

JavaScript, um den Effekt des Klickens auf das Untermenü zu erzielen

In diesem Artikel wird der spezifische JavaScript...

Detailliertes Beispiel für MySQL-Datenspeicherprozessparameter

Es gibt drei Typen von MySQL-gespeicherten Prozed...

Verwendung von Docker-Image-Speicher-Overlays

1. Übersicht Das Image in Docker ist in Schichten...

So stellen Sie MySQL-Master und -Slave in Docker bereit

Bild herunterladen Auswählen eines MySQL-Images D...

Tiefgreifendes Verständnis der Rolle von Vuex

Inhaltsverzeichnis Überblick So teilen Sie Daten ...

Erstellen eines statischen Jenkins Docker-Agentknotens

Ein statischer Knoten ist auf einer Maschine fixi...