Unabhängig davon, welche Plattform Sie verwenden, ist die Protokollierung häufig eine Kernanforderung für die Verarbeitung großer Datenmengen, Statistiken, Prüfungen, Clientberichte und Transaktionen sowie für die Fehlerbehebung bei der Client-Server-Kommunikation und möglichen Problemen.
In diesem Blog beschäftigen wir uns mit der Rolle der Protokollierung beim Debuggen, da sie das ultimative Werkzeug zum Auffinden der verschiedenen, bei der Internetkommunikation so häufig auftretenden Probleme darstellt.
Durch die Protokollierung der Client-Webserver-Kommunikation lässt sich viel leichter beheben, wenn es um die Fehlerbehebung bei möglichen Problemen im Zusammenhang mit der Browserversion, dem Netzwerk des Clients und den aufgerufenen Dateien geht. Damit ist es jedoch nicht beendet. Es gibt endlose Möglichkeiten, was Sie protokollieren möchten, ganz abhängig von Ihrer Plattform und Ihren Anforderungen.
Wenn Sie einen Reverseproxy, einen Load Balancer oder ein Content Delivery Network (CDN) ausführen, fügen Sie dem Kommunikationsfluss zwischen Client und Server einen weiteren Knoten hinzu. Ein Zwischenserver, der Daten manipuliert, wie etwa ein Reverse-Proxy, führt häufig zu unerwarteten Problemen.
Als Reverse-Proxy wandelt NGINX die Verbindung vom Client zum Webserver (oder einem anderen App-Server) in zwei separate Verbindungen um, indem es die Verbindung vom Client beendet und eine neue zum Server herstellt. Durch die „Aufteilung“ in zwei Verbindungen werden auch zwei separate Kontexte für die Protokollierung erstellt, und NGINX unterstützt die Protokollierung für diese etwas anders.
Für den Datenverkehr zwischen dem Client und dem Reverse-Proxy stellt NGINX sowohl ein Fehlerprotokoll als auch ein Zugriffsprotokoll bereit, in dem Verarbeitungsereignisse und Aktionen aufgezeichnet werden, bei denen es sich nicht um Fehler handelt.
Mit der Direktive error_log
aktivieren Sie das Fehlerprotokoll und können den Schweregrad der zu protokollierenden Fehler festlegen.
Sie aktivieren das Zugriffsprotokoll mit der Direktive access_log
. Mit der zugehörigen log_format-
Direktive können Sie die Art der in den Protokollen enthaltenen Informationen und das Format der Protokolleinträge anpassen. Sie können die Protokolle in eine Datei, ins Syslog oder in beides schreiben.
Für den Datenverkehr zwischen dem Reverse-Proxy und dem Web- oder App-Server (den NGINX als Upstream-Server bezeichnet) unterstützt NGINX das Fehlerprotokoll. Eine Zugriffsprotokollierung für diesen Datenverkehr wird jedoch nicht unterstützt.
Die einzige Möglichkeit, fehlerfreie Ereignisse zwischen dem Proxyserver und einem Upstreamserver anzuzeigen, besteht darin, den Schweregrad im Fehlerprotokoll auf „debug“
zu setzen. Der Nachteil dieser Einstellung besteht darin, dass große Datenmengen protokolliert werden. Dies verlangsamt die Anforderungsverarbeitung und erstellt sehr große Dateien, die den Speicher schnell füllen können. (Beachten Sie, dass Sie NGINX auch mit dem Argument --with-debug
im Konfigurationsbefehl
neu kompilieren müssen, da die Unterstützung für das Debuggen standardmäßig nicht aktiviert ist.)
Als CDN-Anbieter stoßen wir häufig auf Upstream-Server, die nicht ordnungsgemäß mit unseren Reverse-Proxy-Servern und -Clients kommunizieren. Die Debug
-Meldungen im Fehlerprotokoll enthalten nicht immer die Informationen, die wir benötigen, um ein Problem mit dem Upstream-Server zu beheben.
Die Lösung war schnell klar: Erstellen Sie ein Upstream-Zugriffsprotokoll, indem Sie eine Funktion hinzufügen, die nur die wesentlichen Informationen aus der Kommunikation zwischen dem Reverse-Proxy und den Upstream-Servern sammelt.
Die allgemeine Idee besteht darin, dass NGINX unsere Funktion jedes Mal aufruft, wenn eine Anfrage an einen Upstream-Server gestellt wird. Dies ermöglicht uns, die gesamte Logik im Zusammenhang mit der Upstream-Protokollierung in der Funktion selbst zu programmieren.
Das Standardmodul ngx_http_upstream_module
verarbeitet Upstream-Anfragen und wir benötigen es, um die Funktion für uns aufzurufen. Das Modul unterstützt diese Funktion derzeit nicht, daher haben wir es gepatcht, um den Rückruf bei Bedarf zu aktivieren.
Die Protokollierung selbst wird in einem separaten Modul gehandhabt, das wir geschrieben haben und das die Protokoll-Rückruffunktion verwendet, die wir im gepatchten Upstream-Modul hinzugefügt haben. Das neue Modul definiert eine neue upstream_log-
Direktive zum Konfigurieren der Protokollierungsfunktion. Die Direktive verwendet denselben Parser wie die access_log-
Direktive, sodass Daten entweder in eine Datei geschrieben oder über einen Socket an einen Syslog-Server gesendet werden können.
Wenn NGINX beim Start die Direktive upstream_log
in nginx.conf liest, werden zwei Funktionen aufgerufen:
ngx_http_upstream_log_set_log
, das die Direktive analysiert und die Protokollstruktur selbst ( ngx_log_t
) vorbereitet, wobei intern ngx_log_set_log
verwendet wirdngx_http_upstream_log_init
(in einem Post-Konfigurationsschritt), das unsere Hauptprotokollierungsfunktion beim Upstream-Modul registriertAuf diese Weise ist alles bereit, wenn eine Anforderung per Upstream-Proxy weitergeleitet werden muss. Das Upstream-Modul stellt eine Verbindung zum Upstream-Server her und unser Patch stellt sicher, dass die Protokollierungsfunktion aufgerufen wird, um die Anforderungsdetails zu protokollieren.
Das Protokollformat ist fest im Upstreammodul verdrahtet. Wir haben immer noch die Möglichkeit, Unterstützung für die Konfiguration mit der log_format-
Direktive hinzuzufügen, aber das ist für unseren Anwendungsfall nicht erforderlich.
Die Protokollierungsfunktion wird direkt nach dem Schließen der Verbindung zum Upstream-Server aufgerufen. Sein Argument ist ein Zeiger auf eine aktuell verarbeitete Anfrage (die ngx_http_request_t
-Struktur), der es der Funktion ermöglicht, auf alle Daten in der Struktur zuzugreifen und diese zu protokollieren. Das Upstream-
Feld (Zeiger auf ngx_http_upstream_t
) ist von besonderem Interesse, da es Daten zur Upstream-Anforderung enthält. Was uns besonders interessiert:
Der Zugriff auf die gesamte Anfragestruktur verleiht dem Modul die nötige Flexibilität, da verschiedenste Informationen protokolliert werden können.
Wir haben die Funktionalität zunächst in ngx_http_core_module
implementiert. Dies war für einen Prototyp gut genug, aber keine sehr saubere Lösung, da es zukünftige Aktualisierungen und Änderungen erschweren könnte. Schließlich haben wir die Upstream-Protokollierungsfunktion in ein eigenständiges Modul ausgegliedert, wie unter „Unsere Upstream-Protokollierungslösung“ beschrieben.
Natürlich gab es einige Implementierungsprobleme. Insbesondere haben wir an einigen Stellen ngx_str_t
-Strings falsch gehandhabt, zum Beispiel indem wir die C-Bibliotheksfunktion sprintf
anstelle von ngx_snprintf
verwendet haben. Dies kann dazu führen, dass undefinierte Daten in das Upstream-Protokoll geschrieben werden oder sogar ein Segmentierungsfehler im Worker-Thread auftritt. Solche Probleme wurden nach umfangreichem Debuggen und Testen mit Tools wie Valgrind und AddressSanitizer gelöst.
Der Hauptgrund, warum CDN77 NGINX verwendet, sind seine Caching-Funktionen. Der CDN-Server ist ein zwischen Client und Webserver (Upstream-Server) eingefügter Knoten, der Client-Anfragen weiterleitet und entsprechende Dateien vom Upstream-Server anfordert. Wenn die Datei zwischengespeichert wird, wird sie an andere Benutzer übermittelt, die die gleiche Datei vom gleichen Speicherort anfordern.
„Lokal bereitgestellte Dateien“ ist eine der Funktionen, die wir verwenden, damit NGINX bei Erhalt einer Anforderung eine Datei von der Festplatte des Servers bereitstellt.
Für sicheres Caching sind einige zusätzliche Funktionen und Konfigurationen erforderlich. Um die Inhalte optimal zu schützen, verwenden wir SSL (TLS 1.3 mit 0‑RTT) oder sichere Token, die für eine bestimmte IP-Adresse generiert werden können.
Zu den weiteren von uns verwendeten Funktionen gehören benutzerdefinierte Fehlerseiten für unsere Clients, die standardmäßige NGINX-Implementierung von OCSP-Stapling und FastCGI für PHP, um die Anzahl der erforderlichen PHP-Prozesse zu reduzieren.
Die Upstream-Protokollierung hat uns nicht nur beim Debuggen verschiedener Probleme geholfen und hilft uns weiterhin dabei, sondern bot auch eine hervorragende Gelegenheit, tiefer in die Kernfunktionalität von NGINX einzutauchen und zahlreiche andere Projekte, die wir durchgeführt haben, zu vereinfachen.
CDN77 macht die Bereitstellung von Inhalten weltweit besser und bequemer. Mit mehr als 30 Rechenzentren sind wir in der Lage, Inhalte weltweit effektiv zwischenzuspeichern und bereitzustellen. Hierzu gehören statische Inhalte auf Ihrer Website, Softwareverteilung, Video-on-Demand (VoD) und Live-Streaming über verschiedene Protokolle wie HLS oder MPEG-DASH unter Verwendung einer dedizierten Streaming-Engine.
Der Einstieg mit CDN77 ist sehr einfach, schnell und unkompliziert. Registrieren Sie sich für eine kostenlose Testversion , erstellen Sie eine CDN-Ressource und verwenden Sie die generierte CDN-URL oder den benutzerdefinierten CNAME-
Eintrag, um sie in Ihre Website oder Streaming-Lösung zu integrieren. Alle Funktionen, Einstellungen und möglichen benutzerdefinierten Lösungen stellen sicher, dass CDN77 Ihren Anforderungen entspricht.
„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."