Wie funktioniert das NGINX-Reload? Warum führt NGINX kein Hot-Reloading durch?
Wei Liu
September 30, 2022
Ich habe kürzlich einen Beitrag auf Reddit bemerkt, in dem es hieß: „Warum unterstützt NGINX kein Hot Reloading?“ Seltsamerweise unterstützt NGINX, der weltweit größte Webserver, kein Hot Reloading? Bedeutet das, dass wir alle nginx -s reload
falsch verwenden? Mit dieser Frage wollen wir uns ansehen, wie das NGINX-Reload funktioniert.
Was ist NGINX
NGINX ist ein plattformübergreifender Open-Source-Webserver, der in der Programmiersprache C entwickelt wurde. Statistiken zufolge verwenden über 40 % der 1000 meistbesuchten Websites NGINX, um die enormen Anfragen zu bewältigen.
Warum ist NGINX so beliebt
Welche Vorteile hat NGINX, um andere Webserver zu übertreffen und stets eine hohe Nutzungsrate zu halten?
Der Hauptgrund ist, dass NGINX für die Bewältigung von Hochlastproblemen entwickelt wurde. Daher kann NGINX einen stabilen und effizienten Dienst bieten, während es enorme gleichzeitige Anfragen bewältigt. Darüber hinaus hat NGINX im Vergleich zu Konkurrenten wie Apache und Tomcat viele außergewöhnliche Designs wie eine fortschrittliche ereignisgesteuerte Architektur, einen vollständig asynchronen Mechanismus zur Handhabung von Netzwerk-IO und ein äußerst effizientes Speicherverwaltungssystem. Diese bemerkenswerten Designs helfen NGINX, die Hardware-Ressourcen der Server vollständig zu nutzen und machen NGINX zum Synonym für Webserver.
Neben den oben genannten Gründen gibt es noch weitere:
- Das hochmodulare Design ermöglicht es NGINX, eine Vielzahl von offiziellen und erweiterten Drittanbieter-Modulen zu besitzen.
- Die freizügige BSD-Lizenz motiviert Entwickler, zu NGINX beizutragen.
- Die Unterstützung von Hot Reloading ermöglicht es NGINX, rund um die Uhr Dienste anzubieten.
Unter diesen Gründen ist Hot Reloading unser heutiges Hauptthema.
Was bewirkt Hot Reloading
Was erwarten wir von Hot Reloading? Erstens sollten Benutzer auf der Client-Seite nichts vom Neuladen des Servers mitbekommen. Zweitens sollten Server oder Upstream-Dienste dynamisches Laden ermöglichen und alle Benutzeranfragen erfolgreich ohne Ausfallzeiten bearbeiten.
Unter welchen Umständen benötigen wir Hot Reloading? In der Cloud-Native-Ära sind Microservices so beliebt geworden, dass immer mehr Anwendungsszenarien häufige Änderungen auf der Serverseite erfordern. Diese Änderungen, wie das Online/Offline-Schalten von Reverse-Proxys für Domänen, Änderungen der Upstream-Adressen und Änderungen der IP-Allowlist/Blocklist, stehen im Zusammenhang mit Hot Reloading.
Wie erreicht NGINX also Hot Reloading?
Das Prinzip des NGINX-Hot-Reloadings
Wenn wir den Hot-Reload-Befehl nginx -s reload
ausführen, sendet er ein HUP-Signal an den Master-Prozess von NGINX. Wenn der Master-Prozess das HUP-Signal empfängt, öffnet er nacheinander die Listening-Ports und startet einen neuen Worker-Prozess. Daher existieren zwei Worker-Prozesse (alt & neu) gleichzeitig. Nachdem der neue Worker-Prozess gestartet ist, sendet der Master-Prozess ein QUIT-Signal an den alten Worker-Prozess, um ihn ordnungsgemäß zu beenden. Wenn der alte Worker das QUIT-Signal empfängt, schließt er zunächst den Listening-Handler. Nun gelangen alle neuen Verbindungen nur noch in den neuen Worker-Prozess, und der Server beendet den alten Prozess, sobald alle verbleibenden Verbindungen verarbeitet sind.
Könnte das Hot Reloading von NGINX theoretisch unsere Anforderungen perfekt erfüllen? Leider lautet die Antwort nein. Welche Nachteile hat also das Hot Reloading von NGINX?
NGINX-Reload verursacht Ausfallzeiten
-
Zu häufiges Hot Reloading kann Verbindungen instabil machen und Geschäftsdaten verlieren.
Wenn NGINX den Reload-Befehl ausführt, verarbeitet der alte Worker-Prozess weiterhin die bestehenden Verbindungen und trennt sich automatisch, sobald alle verbleibenden Anfragen verarbeitet sind. Wenn der Client jedoch nicht alle Anfragen verarbeitet hat, gehen die Geschäftsdaten der verbleibenden Anfragen für immer verloren. Dies würde natürlich die Aufmerksamkeit der Benutzer auf der Client-Seite erregen.
-
In einigen Fällen dauert das Recycling des alten Worker-Prozesses so lange, dass es den regulären Geschäftsbetrieb beeinträchtigt.
Zum Beispiel, wenn wir das WebSocket-Protokoll proxyen, können wir nicht wissen, ob eine Anfrage verarbeitet wurde, da NGINX den Header-Frame nicht analysiert. Selbst wenn der Worker-Prozess das Beenden-Kommando vom Master-Prozess empfängt, kann er erst beenden, wenn diese Verbindungen Ausnahmen auslösen, timeouts haben oder getrennt werden.
Ein weiteres Beispiel ist, wenn NGINX als Reverse-Proxy für TCP und UDP fungiert, kann es nicht wissen, wie oft eine Anfrage gestellt wird, bevor sie schließlich beendet wird.
Daher dauert der alte Worker-Prozess normalerweise sehr lange, insbesondere in Branchen wie Live-Streaming, Medien und Spracherkennung. Manchmal kann die Recycling-Zeit des alten Worker-Prozesses eine halbe Stunde oder sogar länger betragen. Wenn Benutzer den Server häufig neu laden, entstehen viele beendende Prozesse, was schließlich zu NGINX OOM führen kann, was den Geschäftsbetrieb ernsthaft beeinträchtigen würde.
# immer vorhanden im alten Worker-Prozess:
nobody 6246 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 6247 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 6247 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 6248 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 6249 6241 0 10:51 ? 00:00:00 nginx: worker process
nobody 7995 10419 0 10:30 ? 00:20:37 nginx: worker process is shutting down <= hier
nobody 7995 10419 0 10:30 ? 00:20:37 nginx: worker process is shutting down
nobody 7996 10419 0 10:30 ? 00:20:37 nginx: worker process is shutting down
Zusammenfassend lässt sich sagen, dass wir Hot Reloading durch die Ausführung von nginx -s reload
erreichen können, was in der Vergangenheit ausreichend war. Die rasante Entwicklung von Microservices und Cloud Native macht diese Lösung jedoch nicht mehr den Anforderungen der Benutzer gerecht.
Wenn die Aktualisierungshäufigkeit Ihres Geschäfts wöchentlich oder täglich ist, dann könnte dieses NGINX-Reloading immer noch Ihre Bedürfnisse erfüllen. Was jedoch, wenn die Aktualisierungshäufigkeit stündlich oder minütlich wird? Angenommen, Sie haben 100 NGINX-Server, und jeder lädt einmal pro Stunde neu, dann müsste er 2400 Mal pro Tag neu laden; Wenn der Server jede Minute neu lädt, dann müsste er 8.640.000 Mal pro Tag neu laden, was inakzeptabel ist.
Wir benötigen eine Lösung ohne Prozesswechsel, die auch sofortige Inhaltsaktualisierungen ermöglicht.
Hot Reloading, das sofort im Speicher wirksam wird
Als Apache APISIX geboren wurde, war es darauf ausgelegt, das NGINX-Hot-Reloading-Problem zu lösen. APISIX basiert auf den Tech-Stacks von NGINX und Lua und ist ein Cloud-nativer, hochleistungsfähiger, vollständig dynamischer Microservice-API-Gateway, der etcd als zentralen Konfigurationsserver verwendet. Es ist kein Neustart des Servers erforderlich, um die neue Serverkonfiguration neu zu laden, was bedeutet, dass Änderungen an Upstream-Diensten, Routen oder Plugins keinen Server-Neustart erfordern. Aber wie kann APISIX die Einschränkungen von NGINX überwinden, um perfektes Hot Reloading zu erreichen, obwohl APISIX auf dem NGINX-Tech-Stack basiert?
Zuerst werfen wir einen Blick auf die Software-Architektur von Apache APISIX:
APISIX kann das perfekte Hot Reloading erreichen, da es alle Konfigurationen in den APISIX Core und das Plugin Runtime legt, sodass sie dynamische Zuweisungen verwenden können. Zum Beispiel, wenn NGINX Parameter in Konfigurationsdateien konfigurieren muss, würde jede Änderung erst nach einem Neuladen wirksam. Um Routen dynamisch zu konfigurieren, konfiguriert Apache APISIX nur einen bestimmten Server mit einem einzigen Standort. Wir müssen diesen Standort als Haupteingang verwenden, sodass alle Anfragen zuerst durch ihn gehen, und dann würde der APISIX Core spezifische Upstreams für sie dynamisch zuweisen. Das Routenmodul von Apache APISIX kann das Hinzufügen/Entfernen, Ändern und Löschen von Routen während des Serverbetriebs unterstützen. Mit anderen Worten, es kann dynamisches Neuladen erreichen. Keine dieser Änderungen würde die Aufmerksamkeit der Benutzer erregen oder den regulären Geschäftsbetrieb beeinträchtigen.
Nun stellen wir ein klassisches Szenario vor; zum Beispiel, wenn wir einen Reverse-Proxy für eine neue Domäne hinzufügen möchten, müssen wir nur einen Upstream in APISIX erstellen und eine neue Route hinzufügen. NGINX muss während dieses Prozesses nicht neu gestartet werden. Hier ist ein weiteres Beispiel für das Plugin-System: APISIX kann ein IP-Restriction-Plugin verwenden, um die IP-Allowlist/Blocklist-Funktion zu erreichen. Alle diese Funktionsaktualisierungen sind dynamisch und erfordern keinen Server-Neustart. Dank etcd kann die Konfigurationsstrategie sofortige Aktualisierungen durch Add-Ons erreichen, und alle Konfigurationen können sofort wirksam werden und das beste Benutzererlebnis bieten.
Fazit
NGINX-Hot-Reloading führt unter bestimmten Umständen zu einem alten und einem neuen Worker-Prozess, was zusätzlichen Ressourcenverbrauch verursacht. Außerdem kann zu häufiges Hot Reloading zu einem geringen Risiko des vollständigen Verlusts von Geschäftsdaten führen. Vor dem Hintergrund von Cloud Native und Microservices werden Dienstaktualisierungen immer häufiger, und die Strategie zur Verwaltung von APIs variiert, was zu neuen Anforderungen an Hot Reloading führt.
Das Hot Reloading von NGINX erfüllt die Geschäftsanforderungen nicht mehr. Es ist an der Zeit, auf Apache APISIX umzusteigen, einen API-Gateway mit einer fortschrittlicheren Hot-Reloading-Strategie in der Cloud-Native-Ära. Darüber hinaus können Benutzer nach dem Wechsel zu APISIX eine dynamische und einheitliche Verwaltung von API-Diensten haben, was die Managementeffizienz erheblich verbessern kann.