BLOG | NGINX

Anwendungsverfolgung mit NGINX und NGINX Plus

NGINX-Teil-von-F5-horiz-schwarz-Typ-RGB
Liam Crilly Miniaturbild
Liam Crilly
Veröffentlicht am 27. September 2016
Foto: WordPress.org

Verwenden von Variablen für das Anwendungsleistungsmanagement

Variablen sind ein wichtiger und manchmal übersehener Aspekt der NGINX-Konfiguration. Mit den ungefähr 150 verfügbaren Variablen können Sie jeden Teil Ihrer Konfiguration verbessern. In diesem Blogbeitrag besprechen wir die Verwendung von NGINX-Variablen für die Anwendungsverfolgung und das Anwendungsleistungsmanagement (APM), wobei der Schwerpunkt auf der Aufdeckung von Leistungsengpässen in Ihrer Anwendung liegt. Dieser Beitrag gilt sowohl für NGINX Open Source als auch für NGINX Plus. Der Kürze halber beziehen wir uns durchgehend auf NGINX Plus, außer wenn es einen Unterschied zwischen den beiden Versionen gibt.

Die Anwendungsbereitstellungsumgebung

In unserer Beispielumgebung zur Anwendungsbereitstellung fungiert NGINX Plus als Reverse-Proxy für unsere Anwendung. Die Anwendung selbst besteht aus einem Web-Frontend, hinter dem eine Reihe von Microservices sitzen.

In einem gängigen Bereitstellungsszenario leitet NGINX oder NGINX Plus Anfragen von Clients an eine Anwendung oder einen Anwendungsserver weiter, der aus einem Web-Frontend und unterstützenden Microservices besteht.
Beispiel für eine Anwendungsbereitstellungsumgebung

End-to-End-Nachverfolgung von Anfragen

NGINX Plus R10 (und NGINX 1.11.0) führt die Variable $request_id ein, eine zufällig generierte Zeichenfolge aus 32 hexadezimalen Zeichen, die jeder eingehenden HTTP-Anfrage automatisch zugewiesen wird (z. B. 444535f9378a3dfa1b8604bc9e05a303 ). Dieser täuschend einfache Mechanismus stellt ein leistungsstarkes Tool zur Verfolgung und Fehlerbehebung bereit. Indem Sie NGINX Plus und alle Backend-Dienste so konfigurieren, dass der Wert $request_id übergeben wird, können Sie jede Anfrage End-to-End verfolgen. Diese Beispielkonfiguration ist für unseren Frontend-NGINX-Plus-Server.

upstream app_server { server 10.0.0.1:80;
}

server {
listen 80;
add_header X-Request-ID $request_id; # Zurück zum Client
location / {
proxy_pass http://app_server;
proxy_set_header X-Request-ID $request_id; # Weiter zum App-Server
}
}

Um NGINX Plus für die Anforderungsverfolgung zu konfigurieren, definieren wir zunächst den Netzwerkstandort des Anwendungsservers im Upstream -Block. Der Einfachheit halber zeigen wir hier nur einen einzigen Anwendungsserver , aber normalerweise würden wir aus Gründen der Hochverfügbarkeit und des Lastausgleichs mehrere verwenden.

Der Anwendungsserverblock definiert, wie NGINX Plus eingehende HTTP-Anfragen verarbeitet. Die Listen- Direktive weist NGINX Plus an, auf Port 80 zu lauschen – dem Standard für HTTP-Verkehr, aber eine Produktionskonfiguration verwendet normalerweise SSL/TLS, um Daten während der Übertragung zu schützen .

Die Direktive „add_header“ sendet den Wert „$request_id“ als benutzerdefinierten Header in der Antwort an den Client zurück. Dies ist zum Testen und auch für Clientanwendungen nützlich, die ihre eigenen Protokolle generieren, wie z. B. mobile Apps, sodass ein clientseitiger Fehler genau den Serverprotokollen zugeordnet werden kann.

Schließlich gilt der Standortblock für den gesamten Anwendungsbereich ( / ), und die Direktive „proxy_pass“ leitet alle Anforderungen einfach an den Anwendungsserver weiter. Die Direktive proxy_set_header ändert die Proxy-Anforderung, indem sie einen HTTP-Header hinzufügt, der an die Anwendung übergeben wird. In diesem Fall erstellen wir einen neuen Header namens X-Request-ID und weisen ihm den Wert der Variable $request_id zu. Unsere Anwendung erhält also die Anforderungs-ID, die von NGINX Plus generiert wurde.

$request_id End-to-End-Protokollierung

Unser Ziel beim Application Tracing besteht darin, im Rahmen des Anwendungsleistungsmanagements Leistungsengpässe im Lebenszyklus der Anforderungsverarbeitung zu identifizieren. Dies erreichen wir, indem wir wichtige Ereignisse während der Verarbeitung protokollieren, damit wir sie später auf unerwartete oder unangemessene Verzögerungen analysieren können.

NGINX Plus konfigurieren

Wir beginnen mit der Konfiguration des Front-End-NGINX Plus-Servers, um $request_id in ein benutzerdefiniertes Protokollierungsformat, trace , aufzunehmen, das für die Datei access_trace.log verwendet wird.

log_format trace '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" "$http_user_agent" ' '"$http_x_forwarded_for" $request_id '; Upstream App-Server { Server 10.0.0.1; } Server { Listen 80; Add-Header X-Request-ID $request_id; # Zurück zum Client-Standort / { Proxy-Pass http://App-Server; Proxy-Set-Header X-Request-ID $request_id; # Weiterleiten an App-Server Access-Log /var/log/nginx/access_trace.log Trace ; # Protokoll $request_id } }

Konfigurieren der Backend-Anwendung

Das Übergeben der Anforderungs-ID an Ihre Anwendung ist zwar schön und gut, hilft aber nicht wirklich bei der Anwendungsverfolgung, es sei denn, die Anwendung tut etwas damit. In diesem Beispiel haben wir eine Python-Anwendung, die von uWSGI verwaltet wird. Lassen Sie uns den Anwendungseinstiegspunkt ändern, um die Anforderungs-ID als Protokollierungsvariable zu erfassen.

von uwsgi importiere set_logvar def main (Umgebung, Startantwort): set_logvar ( 'requestid' , Umgebung[ 'X_REQUEST_ID' ])

Dann können wir die uWSGI-Konfiguration ändern, um die Anforderungs-ID in die Standardprotokolldatei aufzunehmen.

Protokollformat = %(Adresse) - %(Benutzer) [%(ltime)] "%(Methode) %(URI) %(Proto)" %(Status) %(Größe) "%(Referer)" "%(Uagent)" %(Angeforderte ID)

Mit dieser Konfiguration erstellen wir jetzt Protokolldateien, die über mehrere Systeme hinweg mit einer einzigen Anfrage verknüpft werden können.

Logeintrag von NGINX:

172.17.0.1 - - [02/Aug/2016:14:26:50 +0000] "GET / HTTP/1.1" 200 90 "-" "-" "-" 5f222ae5938482c32a822dbf15e19f0f

Logeintrag aus der Anwendung:

192.168.91.1 - - [02/Aug/2016:14:26:50 +0000] "GET / HTTP/1.0" 200 123 "-" "-" 5f222ae5938482c32a822dbf15e19f0f

Durch Abgleichen der Transaktionen mit den Anforderungs-ID-Feldern können wir mithilfe von Tools wie Splunk und Kibana Leistungsengpässe in Ihrem Anwendungsserver identifizieren. Wir können beispielsweise nach Anfragen suchen, deren Ausführung länger als zwei Sekunden gedauert hat. Allerdings reicht die standardmäßige Zeitauflösung von einer Sekunde in regulären Zeitstempeln für die meisten Analysen in der Praxis nicht aus.

Hochpräzises Timing

Um Anfragen End-to-End genau messen zu können, benötigen wir Zeitstempel mit einer Genauigkeit im Millisekundenbereich. Durch die Aufnahme der Variable „$msec“ in die Protokolleinträge erhalten wir für jeden Eintrag eine Millisekundenauflösung für den Zeitstempel. Durch das Hinzufügen von Millisekunden-Zeitstempeln zu unserem Anwendungsprotokoll können wir nach Anforderungen suchen, deren Ausführung mehr als 200 Millisekunden statt 2 Sekunden gedauert hat.

Aber selbst dann erhalten wir nicht das vollständige Bild, da NGINX Plus den $msec -Zeitstempel erst am Ende der Verarbeitung jeder Anfrage schreibt. Glücklicherweise gibt es mehrere andere NGINX Plus-Timing-Variablen mit Millisekundenpräzision, die uns mehr Einblick in die Verarbeitung selbst geben:

  • $request_time – Vollständige Anforderungszeit, beginnend, wenn NGINX Plus das erste Byte vom Client liest und endend, wenn NGINX Plus das letzte Byte des Antworttexts sendet
  • $upstream_connect_time – Zeit, die zum Herstellen einer Verbindung mit dem Upstream-Server benötigt wurde
  • $upstream_header_time – Zeit zwischen dem Herstellen einer Verbindung zum Upstream-Server und dem Empfang des ersten Bytes des Antwortheaders
  • $upstream_response_time – Zeit zwischen dem Herstellen einer Verbindung zum Upstream-Server und dem Empfang des letzten Bytes des Antworttexts

Ausführliche Informationen zu diesen Zeitvariablen finden Sie unter Verwenden der NGINX-Protokollierung zur Anwendungsleistungsüberwachung .

Erweitern wir unsere log_format- Direktive, um alle diese hochpräzisen Zeitvariablen in unser Trace- Log-Format aufzunehmen.

log_format trace '$remote_addr - $remote_user [$time_local] "$request" $status ' '$body_bytes_sent "$http_referer" "$http_user_agent" ' '"$http_x_forwarded_for" $request_id $msec $request_time ' '$upstream_connect_time $upstream_header_time $upstream_response_time' ;

Mit unserem bevorzugten Protokollanalysetool können wir Variablenwerte extrahieren und die folgende Berechnung durchführen, um zu sehen, wie lange NGINX Plus zum Verarbeiten der Anfrage gebraucht hat, bevor eine Verbindung zum Anwendungsserver hergestellt wurde:

NGINX Plus-Verarbeitungszeit = $request_time – $upstream_connect_time – $upstream_response_time

Wir können auch nach den höchsten Werten von $upstream_response_time suchen, um zu sehen, ob sie mit bestimmten URIs oder Upstream-Servern verknüpft sind. Und diese können dann weiter mit Anwendungsprotokolleinträgen verglichen werden, die dieselbe Anforderungs-ID haben.

Abschluss

Die Verwendung der neuen Variable „$request_id“ und einiger oder aller Variablen mit Millisekundengenauigkeit kann hervorragende Einblicke in die Leistungsengpässe Ihrer Anwendung bieten und so die Anwendungsleistungsverwaltung verbessern, ohne auf schwergewichtige Agenten und Plug-Ins zurückgreifen zu müssen.

Probieren Sie die Anwendungsverfolgung mit NGINX Plus selbst aus: Starten Sie noch heute Ihre kostenlose 30-Tage-Testversion oder kontaktieren Sie uns, um Ihre Anwendungsfälle zu besprechen .


„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."