BLOG | NGINX

OpenTracing für NGINX und NGINX Plus

NGINX-Teil-von-F5-horiz-schwarz-Typ-RGB
Mohamed Gougam Miniaturbild
Mohamed Gougam
Veröffentlicht am 17. Juni 2019

Trotz aller Vorteile bringt eine Microservices -Architektur auch neue Komplexitäten mit sich. Eine davon ist die Herausforderung, Anfragen während ihrer Verarbeitung zu verfolgen, wobei die Daten zwischen allen Mikrodiensten fließen, aus denen die Anwendung besteht. Zu diesem Zweck wurde eine neue Methode namens Distributed (Request) Tracing entwickelt. OpenTracing ist eine Spezifikation und ein Standardsatz von APIs, die als Leitfaden für die Entwicklung und Implementierung von Distributed-Tracing-Tools dienen sollen.

In NGINX Plus Release 18 (R18) haben wir das NGINX OpenTracing-Modul zu unserem Repository für dynamische Module hinzugefügt (es ist seit einigen Jahren als Drittanbietermodul auf GitHub verfügbar). Ein großer Vorteil des NGINX OpenTracing-Moduls besteht darin, dass Sie durch die Instrumentierung von NGINX und NGINX Plus für verteiltes Tracing Tracing-Daten für jede geproxiete Anwendung erhalten, ohne die Anwendungen einzeln instrumentieren zu müssen.

In diesem Blog zeigen wir, wie Sie die verteilte Ablaufverfolgung von Anfragen für NGINX oder NGINX Plus aktivieren (der Kürze halber beziehen wir uns von nun an nur noch auf NGINX Plus ). Wir stellen Anweisungen für zwei verteilte Tracing-Dienste ( Tracer in der OpenTracing-Terminologie) bereit, Jaeger und Zipkin . (Eine Liste anderer Tracer finden Sie in der OpenTracing-Dokumentation .) Um die Art der von Tracern bereitgestellten Informationen zu veranschaulichen, vergleichen wir die Anforderungsverarbeitung vor und nach der Aktivierung des NGINX Plus-Caching.

Ein Tracer besteht aus zwei Grundkomponenten:

  • Ein Agent, der Ablaufverfolgungsdaten von Anwendungen sammelt, die auf dem Host ausgeführt werden, auf dem er ausgeführt wird. In unserem Fall ist die „Anwendung“ NGINX Plus und der Agent ist als Plug-in implementiert.
  • Ein Server (auch Collector genannt), der Tracing-Daten von einem oder mehreren Agenten entgegennimmt und in einer zentralen Benutzeroberfläche anzeigt. Sie können den Server auf dem NGINX Plus-Host oder einem anderen Host Ihrer Wahl ausführen.

Installieren eines Tracer-Servers

Der erste Schritt besteht darin, den Server für den Tracer Ihrer Wahl zu installieren und zu konfigurieren. Wir stellen Anweisungen für Jaeger und Zipkin bereit. Passen Sie diese bei Bedarf für andere Tracer an.

Installieren des Jaeger-Servers

Zur Installation des Jaeger-Servers empfehlen wir folgende Vorgehensweise. Sie können Docker-Images auch unter der in Schritt 1 angegebenen URL herunterladen.

  1. Navigieren Sie zur Jaeger-Downloadseite und laden Sie die Linux-Binärdatei herunter (zum Zeitpunkt des Schreibens jaeger-1.12.0-linux-amd64.tar ).

  2. Verschieben Sie die Binärdatei nach /usr/bin/jaeger (erstellen Sie ggf. zuerst das Verzeichnis) und führen Sie sie aus.

    $ mkdir /usr/bin/jaeger $ mv jaeger-1.12.0-linux-amd64.tar /usr/bin/jaeger $ cd /usr/bin/jaeger $ tar xvzf jaeger-1.12.0-linux-amd64.tar.gz $ sudo rm -rf jaeger-1.12.0-linux-amd64.tar.gz $ cd jaeger-1.12.0-linux-amd64 $ ./jaeger-all-in-one
  3. Überprüfen Sie, ob Sie in Ihrem Browser unter http:// Jaeger-Server-IP-Adresse :16686/ auf die Jaeger-Benutzeroberfläche zugreifen können (16686 ist der Standardport für den Jaeger-Server).

Installieren des Zipkin-Servers

  1. Laden Sie ein Docker-Image von Zipkin herunter und führen Sie es aus (wir verwenden Port 9411, den Standard).

    $ docker run -d -p 9411:9411 openzipkin/zipkin
  2. Überprüfen Sie, ob Sie in Ihrem Browser unter http:// Zipkin-Server-IP-Adresse :9411/ auf die Zipkin-Benutzeroberfläche zugreifen können.

Installieren und Konfigurieren eines Tracer-Plug-Ins

Führen Sie diese Befehle auf dem NGINX Plus-Host aus, um das Plug-in für Jaeger oder Zipkin zu installieren.

Installieren des Jaeger-Plug-Ins

  1. Installieren Sie das Jaeger-Plug-In. Der folgende wget -Befehl ist für x86‑64-Linux-Systeme:

    $ cd /usr/local/lib $ wget https://github.com/jaegertracing/jaeger-client-cpp/releases/download/v0.4.2/libjaegertracing_plugin.linux_amd64.so -O /usr/local/lib/libjaegertracing_plugin.so

    Anweisungen zum Erstellen des Plug-Ins aus dem Quellcode sind auf GitHub verfügbar.

  2. Erstellen Sie eine JSON‑formatierte Konfigurationsdatei für das Plug‑In mit dem Namen /etc/jaeger/jaeger-config.json und dem folgenden Inhalt. Wir verwenden den Standardport für den Jaeger-Server, 6831:

    { "Dienstname": "nginx", "Sampler": { "Typ": "const", "Param": 1 }, "reporter": { "localAgentHostPort": " Jaeger-Server-IP-Adresse : 6831" } }

    Einzelheiten zum Sampler -Objekt finden Sie in der Jaeger-Dokumentation .

Installieren des Zipkin-Plug-Ins

  1. Installieren Sie das Zipkin-Plug-In. Der folgende wget -Befehl ist für x86‑64-Linux-Systeme:

    $ cd /usr/local/lib $ wget -O - https://github.com/rnburn/zipkin-cpp-opentracing/releases/download/v0.5.2/linux-amd64-libzipkin_opentracing_plugin.so.gz | gunzip -c > /usr/local/lib/libzipkin_opentracing_plugin.so
  2. Erstellen Sie eine JSON‑formatierte Konfigurationsdatei für das Plug‑In mit dem Namen /etc/zipkin/zipkin-config.json und dem folgenden Inhalt. Wir verwenden den Standardport für den Zipkin-Server, 9411:

    { "Dienstname": "nginx", "Collector-Host": " Zipkin-Server-IP-Adresse ", "Collector_Port": 9411 }

    Einzelheiten zu den Konfigurationsobjekten finden Sie im JSON-Schema auf GitHub .

Konfigurieren von NGINX Plus

Führen Sie diese Anweisungen auf dem NGINX Plus-Host aus.

  1. Installieren Sie das NGINX OpenTracing-Modul gemäß den Anweisungen im NGINX Plus Admin Guide .

  2. Fügen Sie die folgende load_module- Direktive im Hauptkontext (oberste Ebene) der Hauptkonfigurationsdatei von NGINX Plus ( /etc/nginx/nginx.conf ) hinzu:

    lade_Module Module/ngx_http_opentracing_module.so;
  3. Fügen Sie der NGINX Plus-Konfiguration die folgenden Anweisungen hinzu.

    Wenn Sie das herkömmliche Konfigurationsschema verwenden, fügen Sie die Anweisungen in eine neue Datei mit dem Namen /etc/nginx/conf.d/opentracing.conf ein. Überprüfen Sie außerdem, ob die folgende Include -Direktive im HTTP- Kontext in /etc/nginx/nginx.conf erscheint:

    http {
    include /etc/nginx/conf.d/*.conf;
    }
    • Die Direktive „opentracing_load_tracer“ aktiviert das Tracer-Plugin. Entfernen Sie je nach Bedarf die Kommentarzeichen aus der Direktive für Jaeger oder Zipkin.
    • Die opentracing_tag -Direktiven machen NGINX Plus-Variablen als OpenTracing-Tags verfügbar, die in der Tracer-Benutzeroberfläche angezeigt werden.
    • Um die OpenTracing-Aktivität zu debuggen, heben Sie die Kommentierung der Anweisungen log_format und access_log auf. Wenn Sie das standardmäßige NGINX-Zugriffsprotokoll und -Protokollformat durch dieses ersetzen möchten, heben Sie die Kommentierung der Anweisungen auf und ändern Sie dann die drei Instanzen von „ opentracing “ in „ main “. Eine andere Möglichkeit besteht darin, die OpenTracing-Aktivität nur für den Datenverkehr auf Port 9001 zu protokollieren. Entfernen Sie dazu die Kommentarzeichen aus den Anweisungen log_format und access_log und verschieben Sie sie in den Serverblock .
    • Der Serverblock richtet OpenTracing für die im nächsten Abschnitt beschriebene Beispiel-Ruby-Anwendung ein.
    # Laden Sie einen Vendor-Tracer#opentracing_load_tracer /usr/local/libjaegertracing_plugin.so 
    # /etc/jaeger/jaeger-config.json;
    #opentracing_load_tracer /usr/local/lib/libzipkin_opentracing_plugin.so
    # /etc/zipkin/zipkin-config.json;
    
    # Aktivieren Sie die Ablaufverfolgung für alle Anfragen
    opentracing on;
    
    # Legen Sie zusätzliche Tags fest, die den Wert der NGINX Plus-Variablen erfassen
    opentracing_tag bytes_sent $bytes_sent;
    opentracing_tag http_user_agent $http_user_agent;
    opentracing_tag request_time $request_time;
    opentracing_tag upstream_addr $upstream_addr;
    opentracing_tag upstream_bytes_received $upstream_bytes_received;
    opentracing_tag upstream_cache_status $upstream_cache_status;
    opentracing_tag upstream_connect_time $upstream_connect_time;
    opentracing_tag upstream_header_time $upstream_header_time;
    opentracing_tag upstream_queue_time $upstream_queue_time;
    opentracing_tag upstream_response_time $upstream_response_time;
    
    #Kommentare zum Debuggen entfernen
    # log_format opentracing '$remote_addr - $remote_user [$time_local] "$request" '
    # '$status $body_bytes_sent "$http_referer" '
    # '"$http_user_agent" "$http_x_forwarded_for" '
    # '"$host" sn="$server_name" '
    # 'rt=$request_time '
    # 'ua="$upstream_addr" us="$upstream_status" '
    # 'ut="$upstream_response_time" ul="$upstream_response_length" '
    # 'cs=$upstream_cache_status';
    #access_log /var/log/nginx/opentracing.log opentracing;
    
    server {
    listen 9001;
    
    location / {
    # Der für OpenTracing Spans verwendete Operationsname ist standardmäßig der Name des
    # 'location'-Blocks, aber heben Sie die Kommentierung dieser Anweisung auf, um sie anzupassen.
    #opentracing_operation_name $uri;
    
    # Verbreiten Sie den aktiven Span-Kontext nach oben, damit die Ablaufverfolgung
    # vom Backend fortgesetzt werden kann.
    opentracing_propagate_context;
    
    # Stellen Sie sicher, dass Ihre Ruby-App auf Port 4567 lauscht
    proxy_pass http://127.0.0.1:4567;
    }
    }
  4. Validieren und laden Sie die NGINX Plus-Konfiguration neu:

    $ nginx -t $ nginx -s neu laden

Einrichten der Ruby-Beispiel-App

Mit der Tracer- und NGINX Plus-Konfiguration erstellen wir eine Beispiel-Ruby-App, die zeigt, wie OpenTracing-Daten aussehen. Mit der App können wir messen, um wie viel das NGINX Plus-Caching die Reaktionszeit verbessert. Wenn die App eine Anfrage wie die folgende HTTP- GET- Anfrage für / empfängt, wartet sie eine zufällige Zeitspanne (zwischen 2 und 5 Sekunden), bevor sie antwortet.

$ curl http:// NGINX-Plus-IP-Adresse :9001/
  1. Installieren und richten Sie sowohl Ruby als auch Sinatra ein (eine Open-Source-Software-Webanwendungsbibliothek und domänenspezifische Sprache, die in Ruby als Alternative zu anderen Ruby-Webanwendungs-Frameworks geschrieben ist).

  2. Erstellen Sie eine Datei namens app.rb mit folgendem Inhalt:

    #!/usr/bin/ruby
    
    require 'sinatra'
    
    get '/*' do
    out = "<h1>Ruby simple app</h1>" + "\n"
    
    #Schlafe eine zufällige Zeit zwischen 2 und 5 Sekunden
    sleeping_time = rand(4)+2
    sleep(sleeping_time)
    puts "geschlafen für: #{sleeping_time}s."
    out += '<p>irgendein Ausgabetext</p>' + "\n"
    
    return out
    end
  3. Machen Sie app.rb ausführbar und führen Sie es aus:

    $ chmod +x app.rb $ ./app.rb

Nachverfolgen von Antwortzeiten ohne Zwischenspeichern

Wir verwenden Jaeger und Zipkin, um zu zeigen, wie lange NGINX Plus braucht, um auf eine Anfrage zu antworten, wenn das Caching nicht aktiviert ist. Für jeden Tracer senden wir fünf Anfragen.

Ausgabe von Jaeger ohne Zwischenspeicherung

Hier sind die fünf Anfragen, die in der Jaeger-Benutzeroberfläche angezeigt werden (aktuellste zuerst):

Hier sind die gleichen Informationen auf der Ruby-App-Konsole:

- -> /geschlafen für: 3 Sek. 
127.0.0.1 - - [07/Jun/2019: 10:50:46 +0000] „GET / HTTP/1.1“ 200 49 3.0028
127.0.0.1 - - [07.06.2019: 10:50:43 UTC] „GET / HTTP/1.0“ 200 49
- -> /
geschlafen für: 2 Sek. 
127.0.0.1 - - [07/Jun/2019: 10:50:56 +0000] "GET / HTTP/1.1" 200 49 2.0018 
127.0.0.1 - - [07.06.2019: 10:50:54 UTC] „GET / HTTP/1.0“1 200 49
- -> /
geschlafen für: 3 Sek. 
127.0.0.1 - - [07/Jun/2019: 10:53:16 +0000] "GET / HTTP/1.1" 200 49 3.0029 
127.0.0.1 - - [07/Jun/2019: 10:53:13 UTC] „GET / HTTP/1.0“ 200 49
- -> /
geschlafen für: 4 Sek.
127.0.0.1 - - [07/Jun/2019: 10:54:03 +0000] "GET / HTTP/1.1" 200 49 4.0030 
127.0.0.1 - - [07/Jun/2019: 10:53:59 UTC] „GET / HTTP/1.0“ 200 49
- -> /
geschlafen für: 3 Sek.
127.0.0.1 - - [07/Jun/2019: 10:54:11 +0000] „GET / HTTP/1.1“ 200 49 3.0012
127.0.0.1 - - [07.06.2019: 10:54:08 UTC] "GET / HTTP/1.0" 200 49

In der Jaeger-Benutzeroberfläche klicken wir auf die erste (aktuellste) Anfrage, um Details dazu anzuzeigen, einschließlich der Werte der NGINX Plus-Variablen, die wir als Tags hinzugefügt haben:

Ausgabe von Zipkin ohne Zwischenspeicherung

Hier sind weitere fünf Anfragen in der Zipkin-Benutzeroberfläche:

Dieselben Informationen auf der Ruby-App-Konsole:

- -> /geschlafen für: 2 Sek.
127.0.0.1 - - [07/Jun/2019: 10:31:18 +0000] "GET / HTTP/1.1" 200 49 2.0021 
127.0.0.1 - - [07.06.2019: 10:31:16 UTC] „GET / HTTP/1.0“ 200 49
- -> /
geschlafen für: 3 Sek.
127.0.0.1 - - [07/Jun/2019: 10:31:50 +0000] "GET / HTTP/1.1" 200 49 3.0029 
127.0.0.1 - - [07/Jun/2019: 10:31:47 UTC] „GET / HTTP/1.0“ 200 49
- -> /
geschlafen für: 3 Sek.
127.0.0.1 - - [07/Jun/2019: 10:32:08 +0000] "GET / HTTP/1.1" 200 49 3.0026 
127.0.0.1 - - [07.06.2019: 10:32:05 UTC] „GET / HTTP/1.0“ 200 49
- -> /
geschlafen für: 3 Sek.
127.0.0.1 - - [07/Jun/2019: 10:32:32 +0000] "GET / HTTP/1.1" 200 49 3.0015 
127.0.0.1 - - [07.06.2019: 10:32:29 UTC] „GET / HTTP/1.0“ 200 49
- -> /
geschlafen für: 5 Sek.
127.0.0.1 - - [07/Jun/2019: 10:32:52 +0000] "GET / HTTP/1.1" 200 49 5.0030 
127.0.0.1 - - [07.06.2019: 10:32:47 UTC] "GET / HTTP/1.0" 200 49

In der Zipkin-Benutzeroberfläche klicken wir auf die erste Anfrage, um Details dazu anzuzeigen, einschließlich der Werte der NGINX Plus-Variablen, die wir als Tags hinzugefügt haben:

Nachverfolgen von Antwortzeiten mit Caching

Konfigurieren des NGINX Plus-Caching

Wir aktivieren das Caching , indem wir Anweisungen zur Datei opentracing.conf hinzufügen, die wir unter „Konfigurieren von NGINX Plus“ erstellt haben.

  1. Fügen Sie im HTTP -Kontext diese Proxy_Cache_Path- Direktive hinzu:

    Proxy-Cache-Pfad /Daten/nginx/Cache Keys_Zone=one:10m;
  2. Fügen Sie im Serverblock die folgenden Anweisungen proxy_cache und proxy_cache_valid hinzu:

    proxy_cache eins;
    proxy_cache_valid beliebig 1m;
  3. Überprüfen und laden Sie die Konfiguration neu:

    $ nginx -t $ nginx -s neu laden

Ausgabe von Jaeger mit Caching

Hier ist die Jaeger-Benutzeroberfläche nach zwei Anfragen.

Die erste Antwort (mit der Bezeichnung 13f69db ) dauerte 4 Sekunden. NGINX Plus hat die Antwort zwischengespeichert, und als die Anforderung etwa 15 Sekunden später wiederholt wurde, dauerte die Antwort weniger als 2 Millisekunden (ms), da sie aus dem NGINX Plus-Cache kam.

Bei genauerer Betrachtung der beiden Anfragen wird der Unterschied in der Antwortzeit deutlich. Bei der ersten Anfrage lautet upstream_cache_status MISS , was bedeutet, dass die angeforderten Daten nicht im Cache waren. Die Ruby-App hat eine Verzögerung von 4 Sekunden hinzugefügt.

Für die zweite Anfrage lautet upstream_cache_status HIT . Da die Daten aus dem Cache kommen, kann die Ruby-App keine Verzögerung hinzufügen und die Reaktionszeit beträgt weniger als 2 ms. Die leeren upstream_*- Werte zeigen auch an, dass der Upstream-Server nicht an dieser Antwort beteiligt war.

Ausgabe von Zipkin mit Caching

Die Anzeige in der Zipkin-Benutzeroberfläche für zwei Anfragen mit aktiviertem Caching zeichnet ein ähnliches Bild:

Und wenn man sich die beiden Anfragen noch einmal im Detail ansieht, erklärt sich der Unterschied in der Antwortzeit. Die Antwort wird für die erste Anforderung nicht zwischengespeichert ( upstream_cache_status ist MISS ) und die Ruby-App fügt (zufällig) dieselbe 4-Sekunden- Verzögerung hinzu wie im Jaeger-Beispiel.

Die Antwort wurde zwischengespeichert, bevor wir die zweite Anfrage stellen, daher ist upstream_cache_status HIT .

Abschluss

Das NGINX OpenTracing-Modul ermöglicht die Verfolgung von NGINX Plus-Anfragen und -Antworten und bietet Zugriff auf NGINX Plus-Variablen mithilfe von OpenTracing-Tags. Auch verschiedene Tracer können mit diesem Modul verwendet werden.

Weitere Einzelheiten zum NGINX OpenTracing-Modul finden Sie im NGINX OpenTracing- Modul-Repo auf GitHub.

Um OpenTracing mit NGINX Plus auszuprobieren, 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."