Kommunikation zwischen Diensten in einem Mikrodienst-Setup

Last reviewed 2024-06-26 UTC

Dieses Dokument ist der dritte 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.

  1. Einführung in Mikrodienste
  2. Monolithische Anwendung in Mikrodienste refaktorieren
  3. Kommunikation zwischen Diensten in Mikrodienst-Einrichtungen (dieses Dokument)
  4. Verteiltes Tracing in Mikrodienstanwendungen

Diese Serie richtet sich an Anwendungsentwickler und Architekten, die Migrationen entwerfen und implementieren, um eine monolithische Anwendung in eine Mikrodienstanwendung zu refaktorieren.

In diesem Dokument werden die Vor- und Nachteile des asynchronen Messaging im Vergleich zu synchronen APIs in Mikrodiensten beschrieben. Das Dokument führt Sie durch die Dekonstruktion einer monolithischen Anwendung und zeigt Ihnen, wie Sie eine synchrone Anfrage in der ursprünglichen Anwendung in einen asynchronen Ablauf in der neuen, auf Mikrodiensten basierenden Einrichtung konvertieren. Diese Konvertierung umfasst die Implementierung zwischen Diensten verteilter Transaktionen.

Beispielanwendung

In diesem Dokument verwenden Sie eine vorgefertigte E-Commerce-Anwendung namens Online Boutique. Die Anwendung implementiert grundlegende E-Commerce-Abläufe wie das Durchsuchen von Artikeln, das Hinzufügen von Produkten in einen Einkaufswagen und die Kasse. Die Anwendung bietet auch Empfehlungen und Anzeigen, die auf der Nutzerauswahl basieren.

Logische Trennung von Diensten

In diesem Dokument isolieren Sie den Zahlungsdienst vom Rest der Anwendung. Alle Abläufe in der ursprünglichen Online Boutique-Anwendung sind synchron. In der refaktorierten Anwendung wird der Zahlungsprozess in einen asynchronen Ablauf umgewandelt. Wenn Sie eine Kaufanfrage erhalten, senden Sie daher keine Bestätigung durch den Nutzer, dass Sie diese sofort verarbeiten. Im Hintergrund wird eine asynchrone Anfrage an den Zahlungsdienst ausgelöst, um die Zahlung zu verarbeiten.

Bevor Sie Zahlungsdaten und -logik in einen neuen Dienst verschieben, isolieren Sie Zahlungsdaten und -logik von der monolithischen Anwendung. Wenn Sie Zahlungsdaten und -logik in der monolithischen Anwendung isolieren, ist es einfacher, Ihren Code in derselben Codebasis zu refaktorieren, falls die Zahlungsdienstgrenzen falsch sind (Geschäftslogik oder -daten).

Die Komponenten der monolithischen Anwendung in diesem Dokument sind bereits modularisiert und daher voneinander isoliert. Wenn Ihre Anwendung engere Abhängigkeiten hat, müssen Sie die Geschäftslogik isolieren und separate Klassen und Module erstellen. Außerdem müssen Sie alle Datenbankabhängigkeiten in ihren eigenen Tabellen entkoppeln und separate Repository-Klassen erstellen. Wenn Sie Datenbankabhängigkeiten entkoppeln, kann es zwischen den aufgeteilten Tabellen zu Fremdschlüsselbeziehungen kommen. Nachdem Sie den Dienst jedoch von der monolithischen Anwendung vollständig entkoppelt haben, sind diese Abhängigkeiten nicht mehr vorhanden und der Dienst interagiert ausschließlich über vordefinierte API- oder RPC-Verträge.

Verteilte Transaktionen und partielle Fehler

Nachdem Sie den Dienst isoliert und von der monolithischen Anwendung getrennt haben, wird eine lokale Transaktion im ursprünglichen monolithischen System auf mehrere Dienste verteilt. In der monolithischen Implementierung folgte der Bezahlvorgang der im folgenden Diagramm gezeigten Sequenz.

Die Bezahlvorgangssequenz wird auf mehrere Dienste verteilt.

Abbildung 1. Ablauf eines Bezahlvorgangs in einer monolithischen Implementierung.

Abbildung 1: Wenn die Anwendung einen Auftrag erhält, ruft der Kassen-Controller den Zahlungsdienst und den Bestelldienst auf, um die Zahlung zu verarbeiten und die Bestellung zu speichern. Wenn einer der Schritte fehlschlägt, kann ein Rollback der Datenbanktransaktion ausgeführt werden. Betrachten Sie ein Beispielszenario, in dem die Bestellanfrage erfolgreich in der Bestelltabelle gespeichert wird, die Zahlung jedoch fehlschlägt. In diesem Szenario wird die gesamte Transaktion zurückgesetzt und der Eintrag aus der Bestelltabelle entfernt.

Nachdem Sie die Zahlung in deren eigenen Dienst entkoppelt haben, sieht der geänderte Bezahlvorgang etwa so aus:

Der Bezahlvorgang umfasst mehrere Dienste und Datenbanken.

Abbildung 2. Eine Abfolge von Bezahlvorgängen, nachdem die Zahlung in einen eigenen Dienst entkoppelt wurde.

Abbildung 2: Die Transaktion umfasst jetzt mehrere Dienste und die entsprechenden Datenbanken; es ist also eine verteilte Transaktion. Nach Eingang einer Bestellung speichert der Kassen-Controller die Bestelldetails in seiner lokalen Datenbank und ruft andere Dienste auf, um die Bestellung abzuschließen. Diese Dienste, z. B. der Zahlungsdienst, können ihre eigene lokale Datenbank zum Speichern von Details zur Bestellung verwenden.

In der monolithischen Anwendung sorgt das Datenbanksystem dafür, dass die lokale Transaktionen atomar sind. Standardmäßig hat das auf Mikrodiensten basierende System, das für jeden Dienst eine separate Datenbank hat, jedoch keinen globalen Transaktionskoordinator, der die verschiedenen Datenbanken umfasst. Da Transaktionen nicht zentral koordiniert sind, werden bei einem Fehler bei der Verarbeitung einer Zahlung keine Änderungen rückgängig gemacht, die per Commit im Bestelldienst vorgenommen wurden. Daher ist der Zustand des Systems inkonsistent.

Folgende Muster werden häufig für die Verarbeitung verteilter Transaktionen verwendet:

  • Zwei-Phasen-Commit-Protokoll (2PC): Teil einer Familie von Konsensprotokollen, 2PC koordiniert die Commit einer verteilten Transaktion und sorgt für Garantien der Atomarität, Konsistenz, Isolation, Langlebigkeit (ACID). Das Protokoll ist in die Phasen Prepare und Commit unterteilt. Transaktion wird nur dann festgeschrieben, wenn alle Teilnehmer sie abgestimmt haben. Wenn die Teilnehmer keinen Konsens erreichen, wird die gesamte Transaktion zurückgesetzt.
  • Saga: Das Splunk-Muster besteht aus der Ausführung lokaler Transaktionen in jedem Mikrodienst, aus dem die verteilte Transaktion besteht. Ein Ereignis wird am Ende jedes erfolgreichen oder fehlgeschlagenen Vorgangs ausgelöst. Alle Mikrodienste, die an der verteilten Transaktion beteiligt sind, abonnieren diese Ereignisse. Wenn die folgenden Mikrodienste ein Erfolgsereignis erhalten, führen sie ihren Vorgang aus. Wenn ein Fehler auftritt, vervollständigen die vorherigen Mikrodienste Aktionen, um Änderungen rückgängig zu machen. Splunk bietet eine konsistente Ansicht des Systems und sorgt dafür, dass nach Abschluss aller Schritte entweder alle Vorgänge erfolgreich sind oder Kosten kompensiert werden, die gesamte Arbeit aufheben.

Wir empfehlen Saga für langlebige Transaktionen. In einer auf Mikrodiensten basierenden Anwendung werden Dienstaufrufe und die Kommunikation mit Systemen von Drittanbietern erwartet. Daher sollte idealerweise das Eventual Consistency-Modell genutzt werden: wiederherstellbare Fehler führen zu Neuversuchen und es werden kompensierende Ereignisse bereitgestellt, die nicht wiederherstellbare Fehler gegebenenfalls beheben.

Es gibt verschiedene Möglichkeiten, eine Saga zu implementieren. Sie können beispielsweise Aufgaben- und Workflow-Engines wie Apache Airflow oder Apache Camel verwenden. Sie können auch eigene Event-Handler mit Systemen schreiben, die auf Kafka, RabbitMQ oder ActiveMQ basieren.

Die Online Boutique-Anwendung nutzt den Checkout-Dienst, um die Zahlungs-, Versand- und E-Mail-Benachrichtigungsdienste zu orchestrieren. Der Checkout-Dienst übernimmt auch den Geschäfts- und Bestellworkflow. Statt Ihre eigene Workflow-Engine zu erstellen, können Sie eine Drittanbieterkomponente wie Zeebe verwenden. Zeebe bietet einen UI-basierten Modellierer. Wir empfehlen Ihnen, die Auswahlmöglichkeiten für Mikrodienst-Orchestratoren anhand der Anforderungen Ihrer Anwendung sorgfältig zu prüfen. Diese Wahl ist für die Ausführung und Skalierung Ihrer Mikrodienste wichtig.

Refaktorierte Anwendung

Damit verteilte Transaktionen in der refaktorierten Anwendung aktiviert werden können, übernimmt der Kassendienst die Kommunikation zwischen Zahlung, Versand und E-Mail-Dienst. Der generische BPMN-Workflow (Business Process Model and Notation) verwendet folgenden Ablauf:

Transaktionen in refaktorierten Anwendungen folgen einem BPMN-Workflow.

Abbildung 3. Einen Bestellworkflow, der verteilte Transaktionen in typischen Mikrodiensten gewährleistet.

Das obige Diagramm zeigt den folgenden Workflow:

  • The frontend service receives an order request and then does the following:
    • Sendet die bestellten Artikel an den Einkaufswagendienst. Anschließend speichert der Einkaufswagendienst die Bestelldetails (Redis).
    • Leitet zur Zahlungsseite weiter. Der Checkout-Dienst ruft Bestellungen vom Einkaufswagendienst ab, legt den Bestellstatus als Pending fest und fordert den Kunden zur Zahlung auf.
    • Bestätigt, dass der Nutzer bezahlt hat Nach der Bestätigung weist der Checkout-Dienst den E-Mail-Dienst an, eine Bestätigungs-E-Mail zu generieren und an den Kunden zu senden.
  • Der Zahlungsdienst verarbeitet die Anfrage anschließend.
    • Ist die Anfrage erfolgreich, aktualisiert der Zahlungsdienst den Bestellstatus in Complete.
    • Wenn die Zahlungsanfrage fehlschlägt, initiiert der Zahlungsdienst eine Ausgleichstransaktion.
      • Die Zahlungsanfrage wird abgebrochen.
      • Der Checkout-Dienst ändert den Bestellstatus in Failed.
    • Wenn der Zahlungsdienst nicht verfügbar ist, tritt nach N Sekunden eine Zeitüberschreitung bei der Anfrage auf und der Checkout-Dienst initiiert eine Ausgleichstransaktion.
    • Der Checkout-Dienst ändert den Bestellstatus in Failed.

Lernziele

  • Stellen Sie die monolithische Anwendung "Online Boutique" in Google Kubernetes Engine (GKE) bereit.
  • Validieren Sie den monolithischen Bezahlvorgang.
  • Mikrodienstversion der refaktorierten monolithischen Anwendung bereitstellen
  • Prüfen Sie, ob der neue Bezahlvorgang funktioniert.
  • Prüfen Sie, ob die verteilten Transaktions- und Ausgleichsaktionen bei einem Fehler funktionieren.

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. Neuen Google Cloud-Nutzern steht möglicherweise eine kostenlose Testversion zur Verfügung.

Nach Abschluss dieses Dokuments können Sie weitere Kosten vermeiden, indem Sie die erstellten Ressourcen löschen. Weitere Informationen finden Sie unter Bereinigen.

Hinweise

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Make sure that billing is enabled for your Google Cloud project.

  3. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  4. Aktivieren Sie die APIs für Compute Engine, Google Kubernetes Engine, Cloud SQL, Artefaktanalyse 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
    
  5. Exportieren Sie die folgenden Umgebungsvariablen:

    export PROJECT=$(gcloud config get-value project)
    export CLUSTER=$PROJECT-gke
    export REGION="us-central1"
    

Monolithische E-Commerce-Anwendung bereitstellen

In diesem Abschnitt stellen Sie die monolithische Online Boutique-Anwendung in einem GKE-Cluster bereit. Die Anwendung verwendet Cloud SQL als relationale Datenbank. Das folgende Diagramm veranschaulicht die monolithische Anwendungsarchitektur:

Die Anwendung nutzt eine monolithische Architektur.

Abbildung 4. Ein Client stellt eine Verbindung zur Anwendung in einem GKE-Cluster her, und die Anwendung eine Verbindung zu einer Cloud SQL-Datenbank.

Um die Anwendung bereitzustellen, führen Sie folgende Schritte aus:

  1. Klonen Sie das GitHub-Repository:

    git clone https://github.com/GoogleCloudPlatform/monolith-to-microservices-example
    
  2. Ersetzen Sie den Platzhalter PROJECT_ID in der Manifestdatei der Terraform-Variablen:

    cd monolith-to-microservices-example/setup && \
    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" terraform.tfvars
    
  3. Führen Sie die Terraform-Skripts aus, um die Einrichtung der Infrastruktur abzuschließen und die Infrastruktur bereitzustellen. Weitere Informationen zu Terraform finden Sie unter Erste Schritte mit Terraform in Google Cloud:

    terraform init && terraform apply -auto-approve
    

    Das Terraform-Skript erstellt Folgendes:

    • Ein VPC-Netzwerk mit dem Namen PROJECT_ID-vpc
    • GKE-Cluster mit dem Namen PROJECT_ID-gke
    • Eine Cloud SQL-Instanz mit dem Namen PROJECT_ID-mysql
      • Eine von der Anwendung verwendete Datenbank namens ecommerce
      • Einen Nutzer root mit dem Passwort password

    Sie können das Terraform-Skript so ändern, dass automatisch ein Passwort generiert wird. Für diese Einrichtung wird ein vereinfachtes Beispiel verwendet, das nicht in der Produktion verwendet werden sollten.

    Die Bereitstellung der Infrastruktur kann bis zu 10 Minuten dauern. Wenn das Skript erfolgreich ist, sieht die Ausgabe so aus:

    ...
    
    Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
    
    Outputs:
    
    kubernetes_cluster_name = PROJECT_ID-gke
    sql_database_name = PROJECT_ID-mysql
    vpc_name = PROJECT_ID-vpc
    
  4. Stellen Sie eine Verbindung zum Cluster her und erstellen Sie einen Namespace mit dem Namen monolith. Sie stellen die Anwendung in einem eigenen Namespace im GKE-Cluster bereit:

    gcloud container clusters get-credentials $CLUSTER \
       --region $REGION \
       --project $PROJECT && \
       kubectl create ns monolith
    
  5. Die in GKE ausgeführte Anwendung verwendet Kubernetes Secrets, um auf die Cloud SQL-Datenbank zuzugreifen. Erstellen Sie ein Secret mit den Nutzeranmeldedaten für die Datenbank:

    kubectl create secret generic dbsecret \
      --from-literal=username=root \
      --from-literal=password=password -n monolith
    
  6. Erstellen Sie das Image der monolithischen Anwendung und laden Sie es in Container Registry hoch:

    cd ~/monolith
    gcloud builds submit --tag gcr.io/$PROJECT_ID/ecomm
    
  7. Aktualisieren Sie den Verweis in der Datei deploy.yaml auf das neu erstellte Docker-Image:

    cd ~/monolith
    sed -i -e "s/\[PROJECT_ID\]/$PROJECT/g" deploy.yaml
    
  8. Ersetzen Sie Platzhalter in den Manifestdateien der Bereitstellung und stellen Sie die Anwendung bereit:

    cd .. && \
    DB_IP=$(gcloud sql instances describe $PROJECT-mysql | grep "ipAddress:" | tail -1 | awk -F ":" '{print $NF}')
    
    sed -i -e "s/\[DB_IP\]/$DB_IP/g" monolith/deploy.yaml
    kubectl apply -f monolith/deploy.yaml
    
  9. Prüfen Sie den Status der Bereitstellung:

    kubectl rollout status deployment/ecomm -n monolith
    

    Die Ausgabe sieht so aus:

    Waiting for deployment "ecomm" rollout to finish: 0 of 1 updated replicas are available...
    deployment "ecomm" successfully rolled out
    
  10. Rufen Sie die IP-Adresse der bereitgestellten Anwendung ab:

    kubectl get svc ecomm -n monolith \
            -o jsonpath="{.status.loadBalancer.ingress[*].ip}" -w
    

    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 URL http://IP_ADDRESS auf die Anwendung zu. Es kann einige Zeit dauern, bis der Load-Balancer fehlerfrei ist und Traffic weiterleitet.

Monolithischen Bezahlvorgang validieren

In diesem Abschnitt erstellen Sie eine Testbestellung, um den Bezahlvorgang zu validieren.

  1. Rufen Sie die URL auf, die Sie im vorherigen Abschnitt notiert haben, http://IP_ADDRESS.
  2. Wählen Sie auf der Startseite der Anwendung ein beliebiges Produkt und klicken Sie dann auf In den Einkaufswagen.
  3. Klicken Sie zum Erstellen eines Testkaufs auf Bestellung aufgeben:
  4. Nach erfolgreicher Kaufabwicklung erscheint das Fenster der Auftragsbestätigung und zeigt eine Auftragsbestätigungs-ID an.
  5. Stellen Sie eine Verbindung zur Datenbank her, um Auftragsdetails aufzurufen:

    gcloud sql connect $PROJECT-mysql --user=root
    

    Sie können auch eine beliebige andere unterstützte Methode verwenden, um eine Verbindung zur Datenbank herzustellen. Geben Sie nach Aufforderung das Passwort als password ein.

  6. Führen Sie folgenden Befehl aus, um die gespeicherten Auftragsdetails aufzurufen:

    select cart_id from ecommerce.cart;
    
  7. Die Ausgabe sieht so aus:

    +--------------------------------------+
    | cart_id                              |
    +--------------------------------------+
    | 7cb9ab11-d268-477f-bf4d-4913d64c5b27 |
    +--------------------------------------+
    

Auf Mikrodiensten basierende E-Commerce-Anwendung bereitstellen

In diesem Abschnitt stellen Sie die refaktorierte Anwendung bereit. In diesem Dokument geht es nur um die Entkopplung von Frontend- und Zahlungsoptionen. Im nächsten Dokument dieser Reihe, Verteiltes Tracing in einer Mikrodienstanwendung, werden andere Dienste wie Empfehlungs- und Anzeigendienste beschrieben, die Sie von der monolithischen Anwendung entkoppeln können. Der Checkout-Dienst verarbeitet die verteilten Transaktionen zwischen dem Frontend und den Zahlungsdiensten und wird im GKE-Cluster als Kubernetes-Dienst bereitgestellt, wie im folgenden Diagramm dargestellt:

Frontend und Zahlungsdienste sind von der monolithischen Anwendung entkoppelt.

Abbildung 5. Der Checkout-Dienst orchestriert Transaktionen zwischen Einkaufswagen-, Zahlungs- und E-Mail-Diensten.

Mikrodienste bereitstellen

In diesem Abschnitt verwenden Sie die zuvor bereitgestellte Infrastruktur, um Mikrodienste in deren eigenen microservice-Namespace bereitzustellen:

  1. Folgende Anforderungen müssen erfüllt sein:

    • Google Cloud-Projekt
    • Shell-Umgebung mit gcloud, git und kubectl
  2. Klonen Sie in Cloud Shell das Mikrodienst-Repository:

    git clone https://github.com/GoogleCloudPlatform/microservices-demo
    cd microservices-demo/
    
  3. Legen Sie das Google Cloud-Projekt und die Region fest und aktivieren Sie die GKE API:

    export PROJECT_ID=PROJECT_ID
    export REGION=us-central1
    gcloud services enable container.googleapis.com \
    --project=${PROJECT_ID}
    

    Ersetzen Sie PROJECT_ID durch die ID Ihres Google Cloud-Projekts.

  4. Erstellen Sie einen GKE-Cluster und rufen Sie die Anmeldedaten dafür ab:

    gcloud container clusters create-auto online-boutique \
        --project=${PROJECT_ID} --region=${REGION}
    

    Die Erstellung eines Clusters kann einige Minuten dauern.

  5. Stellen Sie Mikrodienste im Cluster bereit:

    kubectl apply -f ./release/kubernetes-manifests.yaml
    
  6. Warten Sie, bis die Pods bereit sind.

    kubectl get pods
    

    Nach einigen Minuten werden die Pods im Status Running angezeigt.

  7. Greifen Sie über die externe IP-Adresse des Frontends in einem Browser auf das Web-Frontend zu:

    kubectl get service frontend-external | awk '{print $4}'
    

    Rufen Sie http://EXTERNAL_IP in einem Webbrowser auf, um auf Ihre Instanz von Online Boutique zuzugreifen.

Neuen Bezahlvorgangsablauf validieren

  1. Um den Bezahlvorgang zu prüfen wählen Sie ein Produkt aus und geben eine Bestellung auf, wie im vorherigen Abschnitt, Validierung des monolithischen Zahlungsvorgangs, beschrieben.
  2. Wenn Sie den Bestellvorgang abgeschlossen haben, wird im Bestätigungsfenster keine Bestätigungs-ID angezeigt. Stattdessen werden Sie im Bestätigungsfenster aufgefordert, Ihren E-Mail-Eingang auf Bestätigungsdetails zu prüfen.
  3. Führen Sie folgenden Befehl aus, um zu prüfen, ob die Bestellung empfangen wurde, der Zahlungsdienst die Zahlung verarbeitet hat und die Bestelldetails aktualisiert wurden:

    kubectl logs -f deploy/checkoutservice --tail=100
    

    Die Ausgabe sieht so aus:

    [...]
    {"message":"[PlaceOrder] user_id=\"98828e7a-b2b3-47ce-a663-c2b1019774a3\" user_currency=\"CAD\"","severity":"info","timestamp":"2023-08-10T04:19:20.498893921Z"}
    {"message":"payment went through (transaction_id: f0b4a592-026f-4b4a-9892-ce86d2711aed)","severity":"info","timestamp":"2023-08-10T04:19:20.528338189Z"}
    {"message":"order confirmation email sent to \"someone@example.com\"","severity":"info","timestamp":"2023-08-10T04:19:20.540275988Z"}
    

    Drücken Sie Ctrl+C, um die Logs zu beenden.

  4. Prüfen Sie, ob die Zahlung erfolgreich war:

    kubectl logs -f deploy/paymentservice -n --tail=100
    

    Die Ausgabe sieht so aus:

    [...]
    {"severity":"info","time":1691641282208,"pid":1,"hostname":"paymentservice-65cc7795f6-r5m8r","name":"paymentservice-charge","message":"Transaction processed: visa ending 0454     Amount: CAD119.30128260"}
    {"severity":"info","time":1691641300051,"pid":1,"hostname":"paymentservice-65cc7795f6-r5m8r","name":"paymentservice-server","message":"PaymentService#Charge invoked with request {\"amount\":{\"currency_code\":\"USD\",\"units\":\"137\",\"nanos\":850000000},\"credit_card\":{\"credit_card_number\":\"4432-8015-6152-0454\",\"credit_card_cvv\":672,\"credit_card_expiration_year\":2039,\"credit_card_expiration_month\":1}}"}
    

    Drücken Sie Ctrl+C, um die Logs zu beenden.

  5. Prüfen Sie, ob eine E-Mail zur Bestellbestätigung gesendet wurde:

    kubectl logs -f deploy/emailservice -n --tail=100
    

    Die Ausgabe sieht so aus:

    [...]
    {"timestamp": 1691642217.5026057, "severity": "INFO", "name": "emailservice-server", "message": "A request to send order confirmation email to kalani@examplepetstore.com has been received."}
    

    Die Lognachrichten für jeden Mikrodienst zeigen an, dass die verteilte Transaktion über die Checkout-, Zahlungs- und E-Mail-Dienste erfolgreich abgeschlossen wurde.

Kompensationsaktion in einer verteilten Transaktion validieren

In diesem Abschnitt wird ein Szenario simuliert, in dem ein Kunde eine Bestellung abgibt und der Zahlungsdienst ausfällt.

  1. Löschen Sie die Zahlungsbereitstellung und den Zahlungsdienst, um die Nichtverfügbarkeit des Dienstes zu simulieren:

    kubectl delete deploy paymentservice && \
    kubectl delete svc paymentservice
    
  2. Kehren Sie noch einmal zur Anwendung zurück und schließen Sie den Kassenvorgang ab. Wenn in diesem Beispiel der Zahlungsdienst nicht antwortet, wird das Zeitlimit der Anfrage überschritten und eine Kompensationsaktion ausgelöst.

  3. Klicken Sie im Frontend der Benutzeroberfläche auf die Schaltfläche Bestellen. Die Ausgabe sollte so aussehen:

    HTTP Status: 500 Internal Server Error
    rpc error: code = Internal desc = failed to charge card: could not charge the card: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp: lookup paymentservice on 34.118.224.10:53: no such host"
    failed to complete the order
    main.(*frontendServer).placeOrderHandler
        /src/handlers.go:360
    
  4. Prüfen Sie die Frontend-Dienstlogs:

    kubectl logs -f deploy/frontend --tail=100
    

    Die Ausgabe sollte so aussehen:

    [...]
    {"error":"failed to complete the order: rpc error: code = Internal desc = failed to charge card: could not charge the card: rpc error: code = Unavailable desc = connection error: desc = \"transport: Error while dialing: dial tcp: lookup paymentservice on 34.118.224.10:53: no such host\"","http.req.id":"0a4cb058-ee9b-470a-9bb1-3a965636022e","http.req.method":"POST","http.req.path":"/cart/checkout","message":"request error","session":"96c94881-a435-4490-9801-c788dc400cc1","severity":"error","timestamp":"2023-08-11T18:25:47.127294259Z"}
    
  5. Prüfen Sie die Checkout-Dienstprotokolle:

    kubectl logs -f deploy/frontend --tail=100
    

    Die Ausgabe sollte so aussehen:

    [...]
    {"message":"[PlaceOrder] user_id=\"96c94881-a435-4490-9801-c788dc400cc1\" user_currency=\"USD\"","severity":"info","timestamp":"2023-08-11T18:25:46.947901041Z"}
    {"message":"[PlaceOrder] user_id=\"96c94881-a435-4490-9801-c788dc400cc1\" user_currency=\"USD\"","severity":"info","timestamp":"2023-08-11T19:54:21.796343643Z"}
    

    Beachten Sie, dass es keinen nachfolgenden Aufruf an den E-Mail-Dienst gibt, um die Benachrichtigung zu senden. Es ist kein Transaktionslog wie payment went through (transaction_id: 06f0083f-fa47-4d91-8258-6d61edfab1ca) vorhanden.

  6. Prüfen Sie die E-Mail-Dienstprotokolle:

    kubectl logs -f deploy/emailservice --tail=100
    

    Beachten Sie, dass für die fehlgeschlagene Transaktion im E-Mail-Dienst keine Logeinträge erstellt werden.

Wenn als Dienstorchestrator ein Fehler auftritt, gibt der Checkout-Dienst einen Fehlerstatus zurück und beendet den Bezahlvorgang.

Bereinigen

Wenn Sie die Schritte im nächsten Dokument dieser Reihe, Verteiltes Tracing in einer Mikrodienstanwendung, ausführen möchten, können Sie Projekt und Ressourcen wiederverwenden, statt sie zu löschen.

Projekt löschen

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. 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:

  1. Führen Sie in Cloud Shell den folgenden Befehl aus:

    cd setup && terraform destroy -auto-approve
    
  2. Führen Sie den folgenden Befehl aus, um den Mikrodienstcluster mithilfe des Google Cloud CLI zu löschen:

    gcloud container clusters delete online-boutique \
        --location $REGION
    

Nächste Schritte