
So starten Sie schnell mit VUE3.0:
Nachdem unser Dienst veröffentlicht wurde, wird er zwangsläufig von der laufenden Umgebung (z. B. Container, PM2 usw.) geplant, Dienst-Upgrades führen zu Neustarts und es kommt zu verschiedenen Ausnahmen Der Prozess stürzt ab. Im Allgemeinen verfügt die laufende Umgebung über eine Zustandsüberwachung des Dienstprozesses, bei der der Prozess neu gestartet wird. Beim Upgrade gibt es auch eine fortlaufende Upgrade-Strategie. Die Planungsstrategie der laufenden Umgebung behandelt unseren Serviceprozess jedoch als Black Box und kümmert sich nicht um die internen Betriebsbedingungen des Serviceprozesses. Daher muss unser Serviceprozess die Planungsaktionen der laufenden Umgebung aktiv erkennen und dann ausführen einige Bereinigungsaktionen beenden.
Deshalb werden wir heute die verschiedenen Situationen klären, die zum Beenden des Node.js-Prozesses führen können, und was wir tun können, indem wir diese Prozessbeendigungsereignisse abhören.
Prinzip:
Wenn ein Prozess beendet werden möchte, gibt es nur zwei Situationen: Die eine besteht darin, dass der Prozess aktiv beendet wird, und die andere darin, dass er ein Systemsignal empfängt, das den Prozess zum Beenden auffordert.
Systemsignalbenachrichtigung Exit
Allgemeine Systemsignale sind im offiziellen Dokument von Node.js aufgeführt. Wir konzentrieren uns hauptsächlich auf einige:
Wenn er ein nicht erzwungenes Exit-Signal empfängt, kann der Node.js-Prozess das Exit-Signal abhören und eine benutzerdefinierte Exit-Logik ausführen. Wir haben beispielsweise ein CLI-Tool geschrieben, dessen Ausführung lange dauert. Wenn der Benutzer den Prozess über Strg + C verlassen möchte, bevor die Aufgabe abgeschlossen ist, kann er zum Warten aufgefordert werden:
const readline = require(' readline');
process.on('SIGINT', () => {
// Wir verwenden readline, um die Interaktion einfach in der Befehlszeile zu implementieren const rl = readline.createInterface({
Eingabe: Process.stdin,
Ausgabe: process.stdout
});
rl.question('Die Aufgabe wurde noch nicht abgeschlossen. Sind Sie sicher, dass Sie den Vorgang beenden möchten?', Antwort => {
if (Antwort === 'Ja') {
console.log('Aufgabenausführung unterbrochen, Prozess beenden');
prozess.exit(0);
} anders {
console.log('Aufgabe wird fortgesetzt...');
}
rl.close();
});
});
// Eine Aufgabe simulieren, deren Ausführung 1 Minute dauert const longTimeTask = () => {
console.log('Aufgabenstart...');
setTimeout(() => {
console.log('task end');
}, 1000 * 60);
};
longTimeTask(); Der Effekt ist wie folgt: Jedes Mal, wenn Strg + C gedrückt wird, wird der Benutzer aufgefordert:

Der Prozess beendet
Node.js aktiv, insbesondere in den folgenden Situationen:
Wir wissen, dass pm2 die Wirkung eines Daemon-Prozesses hat. Wenn Ihr Prozess mit einem Fehler beendet wird, implementieren wir auch die Wirkung eines Daemons untergeordneter Prozess im Cluster-Modus von Node.js (eigentlich hat pm2 eine ähnliche Logik):
const cluster = require('cluster' );
const http = require('http');
const numCPUs = require('os').cpus().length;
const Process = require('process');
//Hauptprozesscode if (cluster.isMaster) {
console.log(`Hauptprozess starten: ${process.pid}`);
// Erstellen Sie basierend auf der Anzahl der CPU-Kerne einen Arbeitsprozess für (let i = 0; i < numCPUs; i++) {
Cluster.fork();
}
//Abhören des Worker-Prozess-Exit-Ereignisses cluster.on('exit', (worker, code, signal) => {
console.log(`Arbeitsprozess ${worker.process.pid} beendet, Fehlercode: ${code || signal}, neu gestartet...`);
//Untergeordneten Prozess neu starten cluster.fork();
});
}
// Worker-Prozesscode if (cluster.isWorker) {
// Auf nicht erfasste Fehlerereignisse achten Process.on('uncaughtException', error => {
console.log(`Im Arbeitsprozess ${process.pid} ist ein Fehler aufgetreten`, Fehler);
process.emit('disconnect');
prozess.exit(1);
});
//Webserver erstellen
// Jeder Arbeitsprozess überwacht Port 8000 (Node.js verarbeitet ihn intern und verursacht keine Portkonflikte)
http.createServer((req, res) => {
res.writeHead(200);
res.end('Hallo Weltn');
}).listen(8000);
console.log(`Arbeitsprozess starten: ${process.pid}`);
} Anwendungspraxis
Die verschiedenen Situationen, in denen der Node.js-Prozess beendet wird, wurden oben analysiert. Jetzt erstellen wir ein Tool zur Überwachung des Prozessausgangs. Wenn der Node.js-Prozess beendet wird, darf der Benutzer seine eigene Exit-Logik ausführen:
// Exit-Hook
//Speichern Sie die Exit-Aufgaben, die ausgeführt werden müssen const task = [];
//Exit-Task hinzufügen const addExitTask = fn => task.push(fn);
const handleExit = (Code, Fehler) => {
// ...handleExit-Implementierung ist unten dargestellt};
//Auf verschiedene Exit-Ereignisse hören Process.on('exit', code => handleExit(code));
// Gemäß den POSIX-Spezifikationen verwenden wir 128 + Signalnummer, um den endgültigen Exit-Code zu erhalten. // Die Signalnummer finden Sie im Bild unten. Sie können kill -l unter dem Linux-System ausführen, um alle Signalnummern zu verarbeiten ('SIGHUP', () => handleExit(128 + 1));
process.on('SIGINT', () => handleExit(128 + 2));
process.on('SIGTERM', () => handleExit(128 + 15));
// Drücken Sie Strg+Pause, um das Signal zu verlassen Process.on('SIGBREAK', () => handleExit(128 + 21));
// Exit-Code 1 stellt einen nicht erfassten Fehler dar, der dazu geführt hat, dass der Prozess beendet wurde process.on('uncaughtException', error => handleExit(1, error));
process.on('unhandledRejection', error => handleExit(1, error)); Signalnummer:

Als nächstes müssen wir die eigentliche Prozess-Exit-Funktion handleExit implementieren, da die vom Benutzer übergebene Aufgabenfunktion synchron oder asynchron sein kann. Wir können Process.nextTick verwenden, um sicherzustellen, dass der Synchronisationscode des Benutzers ausgeführt wurde, was leicht verständlich ist .nextTick wird ausgeführt, nachdem die synchrone Codeausführung in jeder Ereignisschleifenphase abgeschlossen ist (verstehen Sie, dass bei asynchronen Aufgaben der Benutzer einen Rückruf aufruft, um uns mitzuteilen, dass die asynchrone Aufgabe abgeschlossen wurde:
// Markieren Sie, ob es ist beendet. Vermeiden Sie mehrere Ausführungen von let isExiting = false;
const handleExit = (Code, Fehler) => {
if (isExiting) return;
isExiting = true;
// Markieren, dass die Exit-Aktion ausgeführt wurde, um mehrere Aufrufe von let hasDoExit = fasle;
const doExit = () => {
if (hasDoExit) return;
hasDoExit = true
Process.nextTick(() => Process.exit(Code))
}
// Aufzeichnen, wie viele asynchrone Aufgaben vorhanden sind let asyncTaskCount = 0;
// Nach Beendigung der asynchronen Aufgabe muss der vom Benutzer aufgerufene Rückruf let ayncTaskCallback = () => {
process.nextTick(() => {
asyncTaskCount--
if (asyncTaskCount === 0) doExit()
})
}
//Alle Exit-Aufgaben ausführen task.forEach(taskFn => {
// Wenn die Anzahl der Parameter der taskFn-Funktion größer als 1 ist, wird davon ausgegangen, dass der Rückrufparameter übergeben wird und es sich um eine asynchrone Aufgabe handelt, wenn (taskFn.length > 1) {
asyncTaskCount++
taskFn(Fehler, ayncTaskCallback)
} anders {
taskFn(Fehler)
}
});
// Wenn es eine asynchrone Aufgabe gibt if (asyncTaskCount > 0) {
// Nach mehr als 10 Sekunden das Beenden erzwingen setTimeout(() => {
doExit();
}, 10 * 1000)
} anders {
doExit()
}
}; An diesem Punkt ist unser Prozess-Exit -
Überwachungstool abgeschlossen. Für die vollständige Implementierung können Sie diese Open-Source-Bibliothek async-exit-hook
anzeigen
verlässt
unseren Webserver, wenn er von einem laufenden Container (pm2 oder Docker usw.) geplant wird oder wenn eine Ausnahme auftritt und der Prozess beendet wird, hoffen wir, Exit-Aktionen durchzuführen, wie z. B. das Abschließen der Antwort auf mit dem verbundene Anforderungen Service, Bereinigen der Datenbankverbindung, Drucken von Fehlerprotokollen, Auslösen von Alarmen usw. Nach Abschluss der Exit-Aktion und anschließendem Beenden des Prozesses können wir jetzt das Prozess-Exit-Überwachungstool verwenden, um Folgendes zu implementieren:
const http = require(' http');
//Webserver erstellen
const server = http.createServer((req, res) => {
res.writeHead(200);
res.end('Hallo Weltn');
}).listen(8000);
// Verwenden Sie das oben entwickelte Tool, um eine Prozess-Exit-Aufgabe hinzuzufügen addExitTask((error, callback) => {
// Fehlerprotokolle drucken, Alarme auslösen, Datenbankverbindungen freigeben usw. console.log('Prozess abnormal beendet', Fehler)
// Keine neuen Anfragen mehr annehmen server.close((error) => {
if (Fehler) {
console.log('Fehler bei der Annahme neuer Anfragen', Fehler)
} anders {
console.log('Akzeptiere keine neuen Anfragen mehr')
}
})
// Ein einfacherer Ansatz besteht darin, eine bestimmte Zeit (hier warten wir 5 Sekunden) auf die Fertigstellung der vorhandenen Anforderungen zu warten. // Wenn Sie vollständig sicherstellen möchten, dass alle Anforderungen verarbeitet werden, müssen Sie jede Verbindung aufzeichnen und warten Alle Verbindungen werden freigegeben. Führen Sie die Exit-Aktion aus. // Sie können sich auf die Open-Source-Bibliothek https://github.com/sebhildebrandt/http-graceful-shutdown beziehen
setTimout(Rückruf, 5 * 1000)
}) Zusammenfassung
Durch den obigen Text sind Ihnen meiner Meinung nach bereits die verschiedenen Situationen bekannt, die dazu führen, dass der Node.js-Prozess beendet wird. Nachdem der Dienst online ist, können Tools wie k8s und pm2 den Prozess zwar kontinuierlich aufrufen, wenn der Prozess abnormal beendet wird, um die Verfügbarkeit des Dienstes sicherzustellen. Wir sollten jedoch auch aktiv die Anomalie oder die Planung des Prozesses im Code erkennen, um z um Probleme früher erkennen zu können.