Dieses Dokument ist der vierte Teil einer vierteiligen Reihe zum Entwerfen, Erstellen und Bereitstellen von Mikrodiensten. In dieser Reihe werden die verschiedenen Elemente einer Mikrodienstarchitektur beschrieben. Die Reihe enthält Informationen zu den Vor- und Nachteilen des Mikrodienstarchitekturmusters und zu ihrer Anwendung.
- Einführung in Mikrodienste
- Monolithische Anwendung in Mikrodienste refaktorieren
- Kommunikation zwischen Diensten in einem Mikrodienst-Setup
- Verteiltes Tracing in einer Mikrodienstanwendung (dieses Dokument)
Diese Serie richtet sich an Anwendungsentwickler und Architekten, die Migrationen entwerfen und implementieren, um eine monolithische Anwendung in eine Mikrodienstanwendung zu refaktorieren.
In einem verteilten System ist es wichtig zu wissen, wie eine Anfrage von einem Dienst zu einem anderen fließt und wie lange es dauert, eine Aufgabe in jedem Dienst auszuführen. Betrachten Sie die auf Mikrodiensten basierende Online Boutique-Anwendung, die Sie im vorherigen Dokument Monolithische Anwendung in Mikrodienste umwandeln bereitgestellt haben. Die Anwendung besteht aus mehreren Diensten. Der folgende Screenshot zeigt beispielsweise die Seite mit den Produktdetails, mit der Informationen von den Frontend-, Empfehlungs- und Anzeigendiensten abgerufen werden.
Um die Seite mit den Produktdetails zu rendern, kommuniziert der Frontend-Dienst mit dem Empfehlungsdienst und dem Anzeigendienst, wie im folgenden Diagramm dargestellt:
Abbildung 1. Dienste, die in verschiedenen Sprachen geschrieben sind.
In Abbildung 1 ist der Frontend-Dienst in Go geschrieben. Der in Python geschriebene Empfehlungsdienst verwendet gRPC, um mit dem Frontend-Dienst zu kommunizieren. Der in Java geschriebene Anzeigendienst verwendet ebenfalls gRPC, um mit dem Frontend-Dienst zu kommunizieren. Neben gRPC kann die dienstübergreifende Kommunikationsmethode auch in REST HTTP sein.
Wenn Sie ein solches verteiltes System aufbauen, sollten Ihre Beobachtbarkeits-Werkzeuge die folgenden Erkenntnisse liefern:
- Die Dienste, die eine Anfrage durchlaufen hat.
- Wo Verzögerungen auftraten, wenn eine Anfrage langsam war.
- Wo ein Fehler aufgetreten ist, wenn die Anfrage fehlgeschlagen ist.
- Wie sich die Ausführung der Anfrage vom normalen Verhalten des Systems unterschied.
- Ob Unterschiede bei der Ausführung der Anfrage auf die Leistung zurückzuführen sind (ob einige Dienstaufrufe länger oder kürzer als gewöhnlich gedauert haben).
Lernziele
- Verwenden Sie Kustomize-Manifestdateien, um die Infrastruktur einzurichten.
- Beispielanwendung „Online Boutique“ in Google Kubernetes Engine (GKE) bereitstellen.
- Verwenden Sie Cloud Trace, um den Weg eines Nutzers in der Beispielanwendung zu prüfen.
Kosten
In diesem Dokument verwenden Sie die folgenden kostenpflichtigen Komponenten von Google Cloud:
Mit dem Preisrechner können Sie eine Kostenschätzung für Ihre voraussichtliche Nutzung vornehmen.
Nach Abschluss dieses Dokuments können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.
Hinweis
Wenn Sie bereits ein Projekt eingerichtet haben, indem Sie das vorherige Dokument dieser Reihe, Interservice-Kommunikation in einer Mikrodiensteinrichtung, abschließen, können Sie das Projekt wiederverwenden. Führen Sie die folgenden Schritte aus, um zusätzliche APIs zu aktivieren und Umgebungsvariablen festzulegen.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, activate Cloud Shell.
Aktivieren Sie die APIs für Compute Engine, GKE, Cloud SQL, Artefaktanalyse, Trace und Container Registry:
gcloud services enable \ compute.googleapis.com \ sql-component.googleapis.com \ servicenetworking.googleapis.com\ container.googleapis.com \ containeranalysis.googleapis.com \ containerregistry.googleapis.com \ sqladmin.googleapis.com
Verteiltes Tracing
Bei der verteilten Tracing-Funktion werden jeder Anfrage kontextbezogene Metadaten hinzugefügt und es wird sichergestellt, dass die Metadaten zwischen den Anfragen geteilt werden. Sie verwenden Trace-Punkte für die instrumentierte verteilte Tracing-Funktion. Sie können beispielsweise Ihre Dienste (Frontend, Empfehlung und Anzeigen) mit zwei Trace-Punkten instrumentieren, um eine Clientanfrage zum Anzeigen der Produktdetails zu verarbeiten: einen Trace-Punkt zum Senden der Anfrage und einen weiteren Trace, um die Antwort zu erhalten. Das folgende Diagramm zeigt, wie diese Trace-Punkt-Instrumentierung funktioniert:
Abbildung 2. Jeder dienstübergreifende Aufruf hat zwei Trace-Punkte, die aus einem Anfrage-Antwort-Paar bestehen.
Damit Trace-Punkte feststellen können, welche Anfrage ausgeführt werden soll, wenn der Dienst aufgerufen wird, übergibt der Ursprungsdienst eine Trace-ID entlang des Ausführungsablaufs. Der Prozess, der die Trace-ID übergibt, wird als Metadatenverteilung oder verteilte Kontextverteilung bezeichnet. Die Kontextverteilung überträgt Metadaten über Netzwerkaufrufe, wenn Dienste einer verteilten Anwendung während der Ausführung einer bestimmten Anfrage miteinander kommunizieren. Das folgende Diagramm zeigt die Weitergabe von Metadaten:
Abbildung 3. Trace-Metadaten werden zwischen Diensten übergeben. Die Metadaten enthalten Informationen wie welcher Dienst ruft welche Zeitstempel auf.
Im Beispiel „Online Boutique“ beginnt ein Trace, wenn ein Nutzer eine erste Anfrage zum Abrufen von Produktdetails sendet. Eine neue Trace-ID wird generiert und jede nachfolgende Anfrage wird mit Headern versehen, die kontextbezogene Metadaten enthalten, die an die ursprüngliche Anfrage zurückgegeben werden.
Jeder einzelne Vorgang, der als Teil der Anfrage des Endnutzers aufgerufen wird, wird als Span bezeichnet. Der ursprüngliche Dienst-Tag hat jeweils eine eigene eindeutige ID und die Trace-ID des übergeordneten Spans. Das folgende Diagramm zeigt eine Trace-Diagrammvisualisierung eines Trace:
Abbildung 4. Ein übergeordneter Span enthält die Antwortzeit untergeordneter Spans.
Abbildung 4 zeigt eine Trace-Struktur, in der der Frontend-Dienst den Empfehlungsdienst und den Anzeigendienst aufruft. Der Frontend-Dienst ist der übergeordnete Span, der die vom Endnutzer beobachtete Antwortzeit beschreibt. Die untergeordneten Spans beschreiben, wie der Empfehlungsdienst und der Anzeigendienst aufgerufen und beantwortet wurden, einschließlich Informationen zur Antwortzeit.
Ein Service Mesh wie Istio ermöglicht das verteilte Tracing von Dienst-zu-Dienst-Traffic ohne spezielle Instrumentierung. Es kann jedoch Situationen geben, in denen Sie mehr Kontrolle über die Traces haben möchten, oder Sie müssen Trace-Code erstellen, der nicht in einem Service Mesh ausgeführt wird.
In diesem Dokument wird OpenTelemetry verwendet, um die Instrumentierung verteilter Mikrodienstanwendungen zu ermöglichen, um Traces und Messwerte zu erfassen. Mit OpenTelemetry können Sie Messwerte und Traces erfassen und dann in Back-Ends exportieren, z. B. Prometheus, Cloud Monitoring, Datadog, Graphite, Zipkin und Jaeger.
Instrumentierung mit OpenTelemetry
In den folgenden Abschnitten wird gezeigt, wie mit der Kontextweitergabe Spans aus mehreren Anfragen an einen einzelnen übergeordneten Trace angehängt werden können.
In diesem Beispiel werden die OpenTelemetry-JavaScript-, Python- und Go-Bibliotheken zur Instrumentierung der Trace-Implementierung für die Zahlungs-, Empfehlungs- und Frontend-Dienste verwendet. Je nach Ausführlichkeit der Instrumentierung können sich Tracing-Daten auf die Kosten des Projekts auswirken (Cloud Trace-Abrechnung). Um die Kosten zu verringern, verwenden die meisten Tracing-Systeme verschiedene Arten der Stichprobenerfassung, um nur einen bestimmten Prozentsatz der beobachteten Traces zu erfassen. In Produktionsumgebungen hat Ihre Organisation möglicherweise Gründe dafür, welche Beispiele sie ausführen möchte und warum. Sie können Ihre Stichprobenstrategie anpassen, indem Sie die Kosten verwalten, sich auf interessante Traces konzentrieren oder Störungen herausfiltern. Weitere Informationen zur Stichprobenerhebung finden sich unter OpenTelemetry-Sampling.
In diesem Dokument wird Trace zur Visualisierung verteilter Traces verwendet. Sie verwenden einen OpenTelemetry-Exporter, um Traces an Trace zu senden.
Trace-Exporter registrieren
In diesem Abschnitt wird beschrieben, wie Sie den Trace-Exporter in jedem Dienst registrieren, indem Sie dem Mikrodienstcode Zeilen hinzufügen.
Für den in Go geschriebenen Frontend-Dienst wird im folgenden Codebeispiel der Exporter registriert:
[...] exporter, err := otlptracegrpc.New( ctx, otlptracegrpc.WithGRPCConn(svc.collectorConn)) if err != nil { log.Warnf("warn: Failed to create trace exporter: %v", err) } tp := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exporter), sdktrace.WithSampler(sdktrace.AlwaysSample())) otel.SetTracerProvider(tp)
Für den Empfehlungsdienst (in Python geschrieben) wird im folgenden Codebeispiel der Exporter registriert:
if os.environ["ENABLE_TRACING"] == "1": trace.set_tracer_provider(TracerProvider()) otel_endpoint = os.getenv("COLLECTOR_SERVICE_ADDR", "localhost:4317") trace.get_tracer_provider().add_span_processor( BatchSpanProcessor( OTLPSpanExporter( endpoint = otel_endpoint, insecure = True ) ) )
Für den Zahlungsdienst (in JavaScript geschrieben) wird im folgenden Codebeispiel der Exporter registriert:
provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter({url: collectorUrl}))); provider.register();
Kontextverteilung einrichten
Das Tracing-System muss einer Trace-Kontextspezifikation folgen, die das Format zum Verteilen des Tracing-Kontexts zwischen Diensten definiert. Beispiele für das Verteilungsformat sind Zipkins B3-Format und X-Google-Cloud-Trace.
OpenTelemetry leitet den Kontext mithilfe des globalen TextMapPropagator
weiter. In diesem Beispiel wird der Trace Context-Propagator verwendet, der das W3C-Traceparent-Format verwendet. Instrumentierungsbibliotheken wie die HTTP- und gRPC-Bibliotheken von OpenTelemetry verwenden den globalen Propagator, um HTTP- oder gRPC-Anfragen den Trace-Kontext als Metadaten hinzuzufügen. Damit die Kontextweitergabe erfolgreich ist, müssen Client und Server dasselbe Weitergabeformat verwenden.
Kontextweitergabe über HTTP
Der Frontend-Dienst fügt einen Trace-Kontext in die HTTP-Anfrageheader ein. Die Back-End-Dienste extrahieren den Trace-Kontext. Das folgende Codebeispiel zeigt, wie der Frontend-Dienst zur Konfiguration des Trace-Kontexts instrumentiert wird:
otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{})) if os.Getenv("ENABLE_TRACING") == "1" { log.Info("Tracing enabled.") initTracing(log, ctx, svc) } else { log.Info("Tracing disabled.") } ... var handler http.Handler = r handler = &logHandler{log: log, next: handler} // add logging handler = ensureSessionID(handler) // add session ID handler = otelhttp.NewHandler(handler, "frontend") // add OpenTelemetry tracing
Kontextweitergabe über gRPC
Betrachten Sie den Ablauf, in dem der Checkout-Dienst die Bestellung basierend auf dem Produkt aufgibt, das ein Nutzer auswählt. Diese Dienste kommunizieren über gRPC.
Im folgenden Codebeispiel wird ein gRPC-Aufruf-Interceptor verwendet, der die ausgehenden Anrufe abfängt und den Trace-Kontext einfügt:
var srv *grpc.Server // Propagate trace context always otel.SetTextMapPropagator( propagation.NewCompositeTextMapPropagator( propagation.TraceContext{}, propagation.Baggage{})) srv = grpc.NewServer( grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()), grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor()), )
Nach Erhalt der Anfrage extrahiert der Zahlungs- oder Produktkatalogdienst (ListProducts
) den Kontext aus den Anfrageheadern und verwendet die übergeordneten Trace-Metadaten, um einen untergeordneten Span zu erzeugen.
In den folgenden Abschnitten wird gezeigt, wie Sie verteiltes Tracing für die Beispielanwendung „Online Boutique“ einrichten und prüfen.
Anwendung bereitstellen
Wenn Sie bereits eine laufende Anwendung aus dem vorherigen Dokument dieser Reihe Dienstübergreifende Kommunikation in einem Mikrodienst-Setup haben, können Sie mit dem nächsten Abschnitt Traces prüfen fortfahren. Führen Sie andernfalls die folgenden Schritte aus, um das Beispiel „Online Boutique“ bereitzustellen:
Klonen Sie in der Cloud Shell das GitHub-Repository:
git clone https://github.com/GoogleCloudPlatform/microservices-demo.git
Setzen Sie für die neue Bereitstellung die Umgebungsvariablen zurück:
PROJECT_ID=PROJECT_ID REGION=us-central1 GSA_NAME=microservices-sa GSA_EMAIL=$GSA_NAME@$PROJECT_ID.iam.gserviceaccount.com
Ersetzen Sie
PROJECT_ID
durch die Google Cloud-Projekt-ID, die Sie verwenden möchten.Optional: Erstellen Sie einen neuen Cluster oder verwenden Sie einen vorhandenen Cluster, falls vorhanden:
gcloud container clusters create-auto online-boutique --project=${PROJECT_ID} --region=${REGION}
Erstellen Sie ein Google-Dienstkonto:
gcloud iam service-accounts create $GSA_NAME \ --project=$PROJECT_ID
APIs aktivieren:
gcloud services enable \ monitoring.googleapis.com \ cloudtrace.googleapis.com \ cloudprofiler.googleapis.com \ --project ${PROJECT_ID}
Weisen Sie dem Dienstkonto die für Cloud Trace erforderlichen Rollen zu:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ --role roles/cloudtrace.agent gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ --role roles/monitoring.metricWriter gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${GSA_NAME}@${PROJECT_ID}.iam.gserviceaccount.com" \ --role roles/cloudprofiler.agent gcloud iam service-accounts add-iam-policy-binding ${GSA_EMAIL} \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/default]"
Annotieren Sie Ihr Kubernetes-Dienstkonto (
default
/default
für den Standard-Namespace), um das IAM-Dienstkonto (Identity and Access Management) zu verwenden:kubectl annotate serviceaccount default \ iam.gke.io/gcp-service-account=${GSA_EMAIL}
Aktivieren Sie die Google Cloud-Observability-Funktion für die GKE-Konfiguration, um das Tracing zu aktivieren:
cd ~/microservices-demo/kustomize && \ kustomize edit add component components/google-cloud-operations
Mit dem vorherigen Befehl wird die Datei
kustomize
/kustomization.yaml
aktualisiert. Sie sieht in etwa so aus:apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - base components: - components/google-cloud-operations [...]
Mikrodienste bereitstellen
kubectl apply -k .
Prüfen Sie den Status der Bereitstellung:
kubectl rollout status deployment/frontend kubectl rollout status deployment/paymentservice kubectl rollout status deployment/recommendationservice kubectl rollout status deployment/adservice
Die Ausgabe für die verschiedenen Befehle sieht so aus:
Waiting for deployment "
" rollout to finish: 0 of 1 updated replicas are available... deployment " " successfully rolled out Rufen Sie die IP-Adresse der bereitgestellten Anwendung ab:
kubectl get service frontend-external | awk '{print $4}'
Warten Sie, bis die IP-Adresse des Load Balancers veröffentlicht wurde. Zum Beenden des Befehls drücken Sie
Ctrl+C
. Notieren Sie sich die IP-Adresse des Load-Balancers und greifen Sie dann unter der URLhttp://IP_ADDRESS
auf die Anwendung zu. Es kann einige Zeit dauern, bis der Load-Balancer fehlerfrei ist und Traffic weiterleitet.
Traces mit Cloud Trace prüfen
Der Kaufprozess eines Nutzers in der Anwendung „Online Boutique“ hat folgenden Ablauf:
- Der Nutzer sieht einen Produktkatalog auf der Landingpage.
- Für einen Kauf klickt der Nutzer auf Kaufen.
- Der Nutzer wird auf eine Produktdetailseite weitergeleitet, auf der er den Artikel dem Einkaufswagen hinzufügt.
- Der Nutzer wird zu einer Zahlungsseite weitergeleitet, auf der er eine Zahlung vornehmen kann, um die Bestellung abzuschließen.
Stellen Sie sich ein Szenario vor, in dem Sie lange Antwortzeiten beim Laden der Seite mit den Produktdetails beheben müssen. Wie bereits beschrieben, besteht die Seite mit den Produktdetails aus mehreren Mikrodiensten. Um zu ermitteln, wo und warum die hohe Latenz auftritt, können Sie verteilte Tracing-Diagramme aufrufen, um die Leistung der gesamten Anfrage für die verschiedenen Dienste zu prüfen.
So prüfen Sie die Grafiken für verteilte Tracing:
- Rufen Sie die Anwendung auf und klicken Sie auf ein beliebiges Produkt. Die Seite mit den Produktdetails wird angezeigt.
- Rufen Sie in der Google Cloud Console die Seite Trace-Liste auf und prüfen Sie die Zeitachse.
- Klicken Sie in der URI-Spalte auf Frontend, um die Ergebnisse des verteilten Traces anzusehen.
In der Trace-Wasserfallansicht werden die Spans angezeigt, die mit dem URI verknüpft sind:
Im vorherigen Screenshot enthält der Trace für ein Produkt die folgenden Spans:
- Der Span Frontend erfasst die End-to-End-Latenz (150.349 ms), die der Client beim Laden der Seite mit den Produktdetails beobachtet.
- Der Span Empfehlungdienst erfasst die Latenz der Back-End-Aufrufe beim Abrufen von Empfehlungen (4,246 ms), die sich auf das Produkt beziehen.
- Der Anzeigendienst-Span erfasst die Latenz der Back-End-Aufrufe beim Abrufen von Anzeigen (4,511 ms), die für die Produktseite relevant sind.
Zur Fehlersuche bei hohen Antwortzeiten können Sie sich Insights ansehen, einschließlich Latenzverteilungsdiagrammen aller Ausreißeranfragen, wenn die Abhängigkeiten des Dienstes ihre Service Level Objectives (SLOs) nicht erfüllen. Sie können außerdem Cloud Trace verwenden, um anhand der Stichproben Leistungsstatistiken zu erhalten und Analyseberichte zu erstellen.
Fehlerbehebung
Wenn die Traces in der Application Performance Management nicht angezeigt werden, prüfen Sie im Log-Explorer, ob der Fehler „Zugriff verweigert“ auftritt. Dieser Fehler tritt auf, wenn das Dienstkonto keinen Zugriff zum Exportieren der Traces hat. Sehen Sie sich die Schritte zum Zuweisen der für Cloud Trace erforderlichen Rollen an und achten Sie darauf, das Dienstkonto mit dem richtigen Namespace zu annotieren. Starten Sie dann opentelemetrycollector
neu:
kubectl rollout restart deployment opentelemetrycollector
Bereinigen
Damit Ihrem Google Cloud-Konto die in dieser Anleitung verwendeten Ressourcen nicht in Rechnung gestellt werden, löschen Sie entweder das Projekt, das die Ressourcen enthält, oder Sie behalten das Projekt und löschen die einzelnen Ressourcen.
Projekt löschen
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Ressourcen löschen
Wenn Sie das in diesem Dokument verwendete Google Cloud-Projekt beibehalten möchten, löschen Sie die einzelnen Ressourcen:
Löschen Sie in Cloud Shell die Ressourcen:
gcloud container clusters delete online-boutique --project=${PROJECT_ID} --region=${REGION}
Nächste Schritte
- Lesen Sie das erste Dokument dieser Reihe, um mehr über Mikrodienste, ihre Vorteile, Herausforderungen und Anwendungsfälle zu erfahren.
- Das zweite Dokument dieser Reihe enthält Informationen zu Strategien für die Refaktorierung von Anwendungen, um Mikrodienste zu unterteilen.
- Im dritten Dokument dieser Reihe erfahren Sie mehr über die Kommunikation zwischen den Diensten in einem Mikrodienst-Setup.
- Weitere Referenzarchitekturen, Diagramme und Best Practices finden Sie im Cloud-Architekturcenter.