Szenarioreproduktion
Im Folgenden werde ich einen nativen Nginx verwenden, um diesen Prozess auf meiner virtuellen Maschine mit installiertem Fedora26 zu reproduzieren. Die von mir verwendete Nginx-Version ist die neueste Version 1.13.4.
Starten Sie zunächst nginx Master und Worker laufen bereits.
Dann senden wir ein sigusr2-Signal an den Master. Wenn der Nginx-Kern dieses Signal empfängt, wird ein Hot-Update ausgelöst.
Sie können sehen, dass der neue Master und die vom Master gegabelten Worker bereits ausgeführt werden. Nach Erhalt dieses Signals sendet der alte Master ein Sigquit seine Arbeiter, sodass der Arbeitsprozess des alten Meisters beendet wird:
Zu diesem Zeitpunkt laufen nur noch der alte Meister, der neue Meister und die Arbeiter des neuen Meisters, was der Situation beim Online-Betrieb ähnelt damals.
Dann verwenden wir den Stoppbefehl:
Wir werden feststellen, dass der neue Master und seine Worker beendet wurden, während der alte Master noch läuft und Worker hervorgebracht hat. Das war damals online die Situation.
Tatsächlich hängt dieses Phänomen mit dem Design von Nginx selbst zusammen: Wenn der alte Master bereit ist, einen neuen Master zu forken, benennt er die Datei nginx.pid in nginx.pid.oldbin um und forkt dann den neuen Master. Der Master erstellt eine neue nginx.pid. Diese Datei zeichnet die PID des neuen Masters auf. Nginx ist der Ansicht, dass die Mission des alten Masters nach Abschluss des Hot-Updates fast beendet ist und jederzeit beendet werden kann, sodass alle nachfolgenden Vorgänge vom neuen Master übernommen werden sollten. Natürlich ist es ungültig, ein weiteres Hot-Update zu versuchen, indem man sigusr2 an den neuen Master sendet, ohne dass der alte Master beendet wird. Der neue Master ignoriert dieses Signal einfach und setzt seine eigene Arbeit fort.
ProblemanalyseBedauerlicher ist, dass die oben erwähnte Lua-Tabelle, die Lua-Datei, die sie definiert, bereits von Luajit in den Speicher geladen und beim Ausführen des init_by_lua-Hooks in Bytecode kompiliert wurde. Das darf der alte Master also offensichtlich nicht tun Ich habe diese Lua-Tabelle, da der Teil des Lua-Codes, den sie lädt, eine alte Version ist. Der Lua-Code, der die Tabelle indiziert, wird während init_by_lua nicht verwendet. Zu diesem Zeitpunkt sind die Codes im Projektverzeichnis alle aktuell, sodass der Worker-Prozess alle im neuesten Code lädt. Wenn diese Arbeitsprozesse verwandte Anforderungen verarbeiten, tritt ein Lua-Laufzeitfehler auf und die externe Manifestation ist der entsprechende http 500. Nachdem wir diese Lektion gelernt haben, müssen wir unseren Nginx-Dienst rationaler herunterfahren. Daher ist ein vernünftigeres Skript zum Starten und Herunterfahren des Nginx-Dienstes erforderlich. Einige im Internet verbreitete Skripte behandeln dieses Phänomen nicht. Wir sollten uns auf das offizielle Skript von Nginx beziehen.Dieser Code stammt aus dem offiziellen Nginx-Dokument /etc/init.d/nginx.
Nginx-Signalsatz
Als nächstes sortieren wir den Nginx-Signalsatz umfassend. Die Quellcodedetails werden hier nicht berücksichtigt. Wir haben zwei Möglichkeiten, Signale an den Master-Prozess zu senden: eine über das Signal nginx -s und die andere darin, es manuell über den Kill-Befehl zu senden. Das Prinzip der ersten Methode besteht darin, einen neuen Prozess zu generieren, der die PID des Master-Prozesses über die Datei nginx.pid erhält, dann das entsprechende Signal an den Master sendet und diesen Prozess dann beendet. Der zweite Weg erfordert, dass wir die Zuordnung des Nginx-Signals zu echten Signalen verstehen. Die folgende Tabelle zeigt ihre Zuordnungsbeziehung: OperationssignalSigup neu laden
Sigusr1 erneut öffnenSigterm stoppen
Quit SigquitHot Update Sigusr2 & Sigwinch & Sigquit
Stop vs Quit
Stop sendet das Sigterm-Signal und zeigt an, dass eine Kraft erforderlich ist Ausgang , und quit wird gesendet. Sigquit bedeutet, ordnungsgemäß zu beenden. Der spezifische Unterschied besteht darin, dass der Arbeitsprozess nach dem Empfang der Sigquit-Nachricht (beachten Sie, dass das Signal nicht direkt gesendet wird, sodass stattdessen die Nachricht verwendet wird) den Listening-Socket schließt und die derzeit inaktive Verbindung schließt (die Verbindung, die vorbelegt werden kann). ) und verarbeiten Sie es dann im Voraus. Alle Timer-Ereignisse werden am Ende beendet. Sofern keine besonderen Umstände vorliegen, sollte quit anstelle von stop verwendet werden.
reload
Nachdem der Master-Prozess sigusr1 empfangen hat, öffnet er alle geöffneten Dateien (z. B. Protokolle) erneut und sendet dann sigusr1-Informationen an jeden Arbeitsprozess. Nachdem der Arbeitsprozess das Signal empfangen hat, führt er den gleichen Vorgang aus. Reopen kann zum Beispiel zum Schneiden von Protokollen verwendet werden:
Hier ist Sleep 1 erforderlich, da zwischen dem Master-Prozess, der die sigusr1-Nachricht an den Worker-Prozess sendet, und dem tatsächlichen erneuten Öffnen von access.log liegt , es gibt Für einen bestimmten Zeitraum schreibt der Arbeitsprozess noch Protokolle in die Datei access.log.0. Durch das Schlafen von 1 Sekunden wird die Integrität der Protokollinformationen von access.log.0 sichergestellt (wenn die Komprimierung direkt ohne Ruhezustand durchgeführt wird, ist es wahrscheinlich, dass ein Protokollverlust auftritt).
Hot-Update
Manchmal muss Nginx diese Funktion während des Entwurfs durchführen, sie kann jedoch nicht über die von Nginx bereitgestellte Befehlszeile durchgeführt werden.
Durch das erneute Auftreten des oben genannten Problems sollten Sie verstanden haben, wie man ein Hot-Update durchführt. Zuerst müssen wir sigusr2 an den aktuellen Master-Prozess senden. Dann wird der Master nginx.pid in nginx.pid.oldbin umbenennen und dann einen neuen forken Erstens verwendet der neue Prozess den Execve-Systemaufruf, um das aktuelle Prozessabbild durch die neue Nginx-Elf-Datei zu ersetzen und zum neuen Master-Prozess zu werden. Nachdem der neue Master-Prozess gestartet ist, führt er das Parsen der Konfigurationsdatei und andere Vorgänge durch und leitet dann den neuen Worker-Prozess aus, um mit der Arbeit zu beginnen.
Dann senden wir das Sigwinch-Signal an den alten Master, und dann sendet der alte Master-Prozess die Sigquit-Nachricht an seinen Worker-Prozess, wodurch der Worker-Prozess beendet wird. Das Senden von Sigwinch und Sigquit an den Master-Prozess führt dazu, dass der Arbeitsprozess beendet wird, ersteres führt jedoch nicht dazu, dass auch der Master-Prozess beendet wird.
Wenn wir schließlich das Gefühl haben, dass der Altmeisterprozess seine Mission erfüllt hat, können wir ihm das Sigquit-Signal senden und ihn beenden lassen.
Wie der Worker-Prozess die Signalnachricht vom Master verarbeitet
Tatsächlich kommuniziert der Master-Prozess mit dem Worker-Prozess, nicht über die Kill-Funktion, sondern über den über die Pipe implementierten Nginx-Kanal. Der Master-Prozess schreibt Informationen in einen Am Ende der Pipe (z. B. Signalinformationen) empfängt der Arbeitsprozess Informationen vom anderen Ende. Das Nginx-Kanalereignis wird dem Ereignisplaner (z. B. Epoll, KQueue) hinzugefügt, wenn der Arbeitsprozess gerade aufsteht Die vom Master gesendeten Daten können vom Ereignisplaner benachrichtigt werden.
nginx ist aus gutem Grund so konzipiert, dass nginx eine extrem hohe Leistung anstrebt und der Signalhandler die Ausführung des Worker-Prozesses unterbricht, wodurch alle Ereignisse für ein Zeitfenster ausgesetzt werden ist ein gewisser Leistungsverlust.
Viele Leute denken vielleicht, dass der Worker-Prozess sofort mit entsprechenden Vorgängen reagiert, wenn er Nginx aufruft Kanal Nach dem Event-Handler verarbeitet Nginx nur einige Flags. Diese Aktionen werden tatsächlich ausgeführt, nachdem eine Runde der Ereignisplanung abgeschlossen ist. Daher gibt es dazwischen ein Zeitfenster, insbesondere wenn das Geschäft komplex und der Verkehr groß ist. Aus diesem Grund erfordert der von Nginx bereitgestellte Protokollschnittplan offiziell Schlafzeiten.
Natürlich können wir den Master-Prozess auch umgehen und Signale direkt an den Worker-Prozess senden. Die Signale, die der Worker verarbeiten kann, sind
Signaleffekt
sigint erzwingen Exit
sigterm erzwingen Exit
sigquit Graceful Exit
sigusr1 öffnen Sie die Datei erneut
Das obige ist der detaillierte Inhalt vonBeispielanalyse des Nginx-Signalsatzes. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!