Trotz all ihrer Vorteile bringt eine Microservices-Architektur auch neue Herausforderungen mit sich. Eine davon besteht darin, Anfragen während ihrer Verarbeitung nachzuverfolgen, wobei Daten zwischen allen Microservices fließen, aus denen die Anwendung besteht. Zu diesem Zweck wurde eine neue Methodik namens verteiltes (Anfrage-)Tracing entwickelt. OpenTracing ist eine Spezifikation und ein standardisierter Satz von APIs, die als Leitfaden für die Konzeption und Implementierung von Tools für verteiltes Tracing dienen.
Mit NGINX Plus Release 18 (R18) haben wir das NGINX OpenTracing-Modul zu unserem Repository für dynamische Module hinzugefügt (es ist bereits 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 über einen Proxy bereitgestellte Anwendung erhalten, ohne die Anwendungen einzeln instrumentieren zu müssen.
In diesem Blog zeigen wir, wie Sie das verteilte Tracing von Anfragen für NGINX oder NGINX Plus aktivieren (der Kürze halber sprechen wir im Folgenden nur noch von NGINX Plus). Wir stellen Anleitungen für zwei Dienste für verteiltes Tracing bereit (in der OpenTracing-Terminologie als Tracer bezeichnet): Jaeger und Zipkin. (Eine Liste weiterer Tracer finden Sie in der OpenTracing-Dokumentation.) Um zu veranschaulichen, welche Informationen Tracer liefern, vergleichen wir die Verarbeitung von Anfragen vor und nach der Aktivierung des Cachings in NGINX Plus.
Ein Tracer besteht aus zwei grundlegenden Komponenten:
- Ein Agent, der Tracing-Daten von Anwendungen erfasst, die auf demselben Host ausgeführt werden wie der Agent. In unserem Fall ist die „Anwendung“ NGINX Plus und der Agent ist als Plug-in implementiert.
- Ein Server (auch als Collector bezeichnet), der Tracing-Daten von einem oder mehreren Agenten entgegennimmt und sie in einer zentralen Benutzeroberfläche anzeigt. Sie können den Server wahlweise auf dem NGINX Plus-Host oder einem anderen Host ausführen.
Installieren eines Tracer-Servers
Im ersten Schritt installieren und konfigurieren Sie den Server für den Tracer Ihrer Wahl. Wir stellen Anleitungen für Jaeger und Zipkin bereit. Passen Sie diese bei Bedarf für andere Tracer an.
Installieren des Jaeger-Servers
Wir empfehlen die folgende Methode zur Installation des Jaeger-Servers. Sie können Docker-Images auch über die in Schritt 1 angegebene URL herunterladen.
- Rufen Sie die Jaeger-Downloadseite auf und laden Sie die Linux-Binärdatei herunter (zum Zeitpunkt der Erstellung: jaeger-1.12.0-linux-amd64.tar).
- Verschieben Sie die Binärdatei nach /usr/bin/jaeger (erstellen Sie das Verzeichnis bei Bedarf zuerst) 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- Ü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 des Jaeger-Servers).
Installieren des Zipkin-Servers
- Laden Sie ein Docker-Image von Zipkin herunter und führen Sie es aus (wir verwenden den Standardport 9411).
$ docker run -d -p 9411:9411 openzipkin/zipkin- Überprüfen Sie, ob Sie in Ihrem Browser unter http://IP-Adresse-des-Zipkin-Servers: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
- Installieren Sie das Jaeger-Plug-in. Der folgende
wget-Befehl ist für x86-64-Linux-Systeme vorgesehen:
$ 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- Eine Anleitung zum Erstellen des Plug-ins aus dem Quellcode finden Sie auf GitHub.
- Erstellen Sie für das Plug-in eine Konfigurationsdatei im JSON-Format mit dem Namen /etc/jaeger/jaeger-config.json und dem folgenden Inhalt. Wir verwenden den Standardport 6831 für den Jaeger-Server:
{ "service_name": "nginx",
"sampler": {
"type": "const",
"param": 1
},
"reporter": {
"localAgentHostPort": "Jaeger-server-IP-address:6831"
}
}- Weitere Informationen zum
sampler-Objekt finden Sie in der Jaeger-Dokumentation.
Installieren des Zipkin-Plug-ins
- Installieren Sie das Zipkin-Plug-in. Der folgende
wget-Befehl ist für x86-64-Linux-Systeme vorgesehen:
$ 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- Erstellen Sie für das Plug-in eine Konfigurationsdatei im JSON-Format mit dem Namen /etc/zipkin/zipkin-config.json und dem folgenden Inhalt. Wir verwenden den Standardport 9411 für den Zipkin-Server:
{ "service_name": "nginx",
"collector_host": "Zipkin-server-IP-address",
"collector_port": 9411
}- Weitere Informationen zu den Konfigurationsobjekten finden Sie im JSON-Schema auf GitHub.
NGINX Plus konfigurieren
Führen Sie diese Schritte auf dem NGINX Plus-Host aus.
- Installieren Sie das NGINX OpenTracing-Modul gemäß den Anweisungen im NGINX Plus-Administratorhandbuch.
- Fügen Sie die folgende
load_module-Direktive im Hauptkontext (auf oberster Ebene) der NGINX Plus-Hauptkonfigurationsdatei (/etc/nginx/nginx.conf) hinzu:
load_module modules/ngx_http_opentracing_module.so;- Fügen Sie der NGINX Plus-Konfiguration die folgenden Direktiven hinzu. Wenn Sie das herkömmliche Konfigurationsschema verwenden, speichern Sie die Direktiven in einer neuen Datei namens /etc/nginx/conf.d/opentracing.conf. Vergewissern Sie sich außerdem, dass die folgende
include-Direktive imhttp-Kontext in /etc/nginx/nginx.conf enthalten ist:
http {
include /etc/nginx/conf.d/*.conf;
}# Load a 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;
# Enable tracing for all requests
opentracing on;
# Set additional tags that capture the value of NGINX Plus variables
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;
#uncomment for debugging
# 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 / {
# The operation name used for OpenTracing Spans defaults to the name of the
# 'location' block, but uncomment this directive to customize it.
#opentracing_operation_name $uri;
# Propagate the active Span context upstream, so that the trace can be
# continued by the backend.
opentracing_propagate_context;
# Make sure that your Ruby app is listening on port 4567
proxy_pass http://127.0.0.1:4567;
}
}- Die Direktive „
opentracing_load_tracer“ aktiviert das Tracer-Plug-in. Entfernen Sie je nach Bedarf bei der Direktive für Jaeger oder Zipkin die Auskommentierung. - Die
opentracing_tag-Direktiven stellen NGINX Plus-Variablen als OpenTracing-Tags bereit, die in der Benutzeroberfläche des Tracers angezeigt werden. - Um OpenTracing-Aktivitäten zu debuggen, entfernen Sie die Kommentarzeichen vor den Direktiven
log_formatundaccess_log. Wenn Sie das standardmäßige NGINX-Zugriffsprotokoll und -Protokollformat durch diese Konfiguration ersetzen möchten, entfernen Sie die Kommentarzeichen vor den Direktiven und ändern Sie anschließend die drei Vorkommen von „opentracing“ in „main“. Alternativ können Sie OpenTracing-Aktivitäten nur für den Datenverkehr auf Port 9001 protokollieren. Entfernen Sie dazu die Kommentarzeichen vor den Direktivenlog_formatundaccess_logund verschieben Sie sie in denserver-Block. - Der
server-Block richtet OpenTracing für die im nächsten Abschnitt beschriebene Ruby-Beispielanwendung ein.
- Validieren Sie die NGINX Plus-Konfiguration und laden Sie sie neu:
$ nginx -t$ nginx -s reloadEinrichten der Ruby-Beispielanwendung
Nachdem der Tracer und NGINX Plus konfiguriert wurden, erstellen wir eine Ruby-Beispielanwendung, die veranschaulicht, wie OpenTracing-Daten aussehen. Mit der Anwendung können wir messen, wie stark das Caching von NGINX Plus die Antwortzeit verbessert. Wenn die Anwendung eine Anfrage wie die folgende HTTP-GET-Anfrage für / erhält, wartet sie eine zufällige Zeitspanne (zwischen 2 und 5 Sekunden), bevor sie antwortet.
$ curl http://NGINX-Plus-IP-address:9001/- Installieren und konfigurieren Sie sowohl Ruby als auch Sinatra (eine in Ruby geschriebene Open-Source-Bibliothek für Webanwendungen und domänenspezifische Sprache, die eine Alternative zu anderen Ruby-Webanwendungsframeworks darstellt).
- Erstellen Sie eine Datei namens „app.rb“ mit folgendem Inhalt:
#!/usr/bin/ruby
require 'sinatra'
get '/*' do
out = "<h1>Ruby simple app</h1>" + "\n"
#Sleep a random time between 2s and 5s
sleeping_time = rand(4)+2
sleep(sleeping_time)
puts "slept for: #{sleeping_time}s."
out += '<p>some output text</p>' + "\n"
return out
end- Machen Sie app.rb ausführbar und führen Sie die Datei aus:
$ chmod +x app.rb$ ./app.rbAntwortzeiten ohne Caching nachverfolgen
Wir verwenden Jaeger und Zipkin, um zu zeigen, wie lange NGINX Plus für die Beantwortung einer Anfrage benötigt, wenn das Caching nicht aktiviert ist. Für jeden Tracer senden wir fünf Anfragen.
Ausgabe von Jaeger ohne Caching
Hier sind die fünf in der Jaeger-Benutzeroberfläche angezeigten Anfragen (die neueste zuerst):

Dieselben Informationen werden auch in der Ruby-App-Konsole angezeigt:
- -> /slept for: 3s.
127.0.0.1 - - [07/Jun/2019: 10:50:46 +0000] "GET / HTTP/1.1" 200 49 3.0028
127.0.0.1 - - [07/Jun/2019: 10:50:43 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 2s.
127.0.0.1 - - [07/Jun/2019: 10:50:56 +0000] "GET / HTTP/1.1" 200 49 2.0018
127.0.0.1 - - [07/Jun/2019: 10:50:54 UTC] "GET / HTTP/1.0"1 200 49
- -> /
slept for: 3s.
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
- -> /
slept for: 4s.
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
- -> /
slept for: 3s.
127.0.0.1 - - [07/Jun/2019: 10:54:11 +0000] "GET / HTTP/1.1" 200 49 3.0012
127.0.0.1 - - [07/Jun/2019: 10:54:08 UTC] "GET / HTTP/1.0" 200 49In der Jaeger-Benutzeroberfläche klicken wir auf die erste (neueste) Anfrage, um Details dazu anzuzeigen, einschließlich der Werte der NGINX Plus-Variablen, die wir als Tags hinzugefügt haben:

Ausgabe von Zipkin ohne Caching
Hier sind fünf weitere Anfragen in der Zipkin-Benutzeroberfläche:

Dieselben Informationen in der Konsole der Ruby-App:
- -> /slept for: 2s.
127.0.0.1 - - [07/Jun/2019: 10:31:18 +0000] "GET / HTTP/1.1" 200 49 2.0021
127.0.0.1 - - [07/Jun/2019: 10:31:16 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 3s.
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
- -> /
slept for: 3s.
127.0.0.1 - - [07/Jun/2019: 10:32:08 +0000] "GET / HTTP/1.1" 200 49 3.0026
127.0.0.1 - - [07/Jun/2019: 10:32:05 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 3s.
127.0.0.1 - - [07/Jun/2019: 10:32:32 +0000] "GET / HTTP/1.1" 200 49 3.0015
127.0.0.1 - - [07/Jun/2019: 10:32:29 UTC] "GET / HTTP/1.0" 200 49
- -> /
slept for: 5s.
127.0.0.1 - - [07/Jun/2019: 10:32:52 +0000] "GET / HTTP/1.1" 200 49 5.0030
127.0.0.1 - - [07/Jun/2019: 10:32:47 UTC] "GET / HTTP/1.0" 200 49In 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:

Antwortzeiten mit Caching nachverfolgen
NGINX Plus-Caching konfigurieren
Wir aktivieren das Caching, indem wir der Datei opentracing.conf, die wir unter „NGINX Plus konfigurieren“ erstellt haben, entsprechende Direktiven hinzufügen.
- Fügen Sie im
http-Kontext die folgendeproxy_cache_path-Direktive hinzu:
proxy_cache_path /data/nginx/cache keys_zone=one:10m;- Fügen Sie im
server-Block die folgenden Direktivenproxy_cacheundproxy_cache_validhinzu:
proxy_cache one;
proxy_cache_valid any 1m;- Validieren Sie die Konfiguration und laden Sie sie neu:
$ nginx -t$ nginx -s reloadAusgabe von Jaeger mit Caching
So sieht die Jaeger-Benutzeroberfläche nach zwei Anfragen aus.

Die erste Antwort (gekennzeichnet mit „13f69db“) dauerte 4 Sekunden. NGINX Plus speicherte die Antwort im Cache. Als die Anfrage etwa 15 Sekunden später wiederholt wurde, dauerte die Antwort weniger als 2 Millisekunden (ms), da sie aus dem NGINX Plus-Cache stammte.
Eine genauere Betrachtung der beiden Anfragen erklärt den Unterschied bei der Antwortzeit. Bei der ersten Anfrage lautet upstream_cache_status MISS, was bedeutet, dass sich die angeforderten Daten nicht im Cache befanden. Die Ruby-App fügte eine Verzögerung von 4 Sekunden hinzu.

Bei der zweiten Anfrage ist upstream_cache_status gleich HIT. Da die Daten aus dem Cache stammen, kann die Ruby-App keine Verzögerung hinzufügen, und die Antwortzeit liegt unter 2 ms. Die leeren upstream_*-Werte weisen ebenfalls darauf hin, dass der Upstream-Server an dieser Antwort nicht beteiligt war.

Ausgabe von Zipkin mit Caching
Die Darstellung in der Zipkin-Benutzeroberfläche zeigt für zwei Anfragen mit aktiviertem Caching ein ähnliches Bild:

Und auch hier erklärt ein genauer Blick auf die beiden Anfragen den Unterschied bei der Antwortzeit. Bei der ersten Anfrage wird die Antwort nicht zwischengespeichert (upstream_cache_status ist MISS) und die Ruby-App fügt (zufälligerweise) dieselbe Verzögerung von 4 Sekunden hinzu wie im Jaeger-Beispiel.

Die Antwort wurde bereits im Cache gespeichert, bevor wir die zweite Anfrage stellen, daher ist upstream_cache_status gleich HIT.

Fazit
Das NGINX OpenTracing-Modul ermöglicht die Ablaufverfolgung von Anfragen und Antworten von NGINX Plus und bietet über OpenTracing-Tags Zugriff auf NGINX Plus-Variablen. Mit diesem Modul können auch verschiedene Tracer verwendet werden.
Weitere Informationen zum NGINX OpenTracing-Modul finden Sie im NGINX OpenTracing-Modul-Repository auf GitHub.
Wenn Sie OpenTracing mit NGINX Plus ausprobieren möchten, starten Sie noch heute Ihre kostenlose 30-Tage-Testversion oder kontaktieren Sie uns, um Ihre Anwendungsfälle zu besprechen.
Über den Autor
Ähnliche Blogbeiträge
Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln
Beim NGINX Sprint 2022 besinnen wir uns auf unsere Open-Source-Wurzeln. Erfahren Sie mehr über die Initiativen, die wir im kommenden Jahr verfolgen, und teilen Sie uns mit, was Sie sich wünschen.

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
Ein Ingress-Controller kann eines der leistungsstärksten Tools in Ihrem Kubernetes-Stack sein. Erfahren Sie, wie Sie Ihre Ingress-Anforderungen ermitteln, um die beste Option auszuwählen.
Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet
Wir haben kürzlich den Lösungsleitfaden zum NGINX Ingress Controller um Empfehlungen zur Dimensionierung für Amazon Elastic Kubernetes Service (EKS) ergänzt. In diesem Blogbeitrag erläutern wir, wie wir diese Empfehlungen erarbeitet haben, und stellen Ihnen alle Informationen zur Verfügung, die Sie benötigen, um selbst ähnliche Tests durchzuführen.

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77
Bei der Fehlersuche bei Datenverkehrsproblemen zwischen NGINX und Upstream-Servern konnte CDN77 die benötigten Daten nur aus dem Fehlerprotokoll mit aktivierter Debug-Ausgabe beziehen, was die Leistung beeinträchtigt und riesige Dateien erzeugt. Daher entwickelte das Team ein neues benutzerdefiniertes Modul, das ausschließlich die benötigten Daten protokolliert.
Ankündigung von NGINX Plus R16
NGINX Plus R16 ist eine einheitliche, elastische Ingress- und Egress-Schicht für Anwendungen, die die Funktionen eines Load Balancers, API-Gateways und einer WAF vereint und neue Features wie clusterfähige Ratenbegrenzung, Schlüssel-Wert-Speicher, „Random with Two Choices“, verbessertes UDP-Load-Balancing und vieles mehr bietet.
5 Gründe für den Umstieg auf softwarebasiertes Load Balancing
Entdecken Sie fünf Gründe für den Wechsel zu einem softwarebasierten Load Balancer wie NGINX Plus, darunter Kosteneinsparungen, die Einführung von DevOps und eine einheitliche Lösung für alle Umgebungen.