1. Wprowadzenie
Ostatnia aktualizacja: 5.03.2021
Dostrzegalność aplikacji
Dostrzegalność i OpenTelemetry
Dostrzegalność to termin opisujący atrybut układu. System z obserwowalnością umożliwia zespołom aktywne debugowanie systemu. W tym kontekście 3 filary dostrzegalności: logi, wskaźniki i logi czasu to podstawowe narzędzia umożliwiające systemowi uzyskiwanie dostrzegalności.
OpenTelemetry to zestaw specyfikacji i pakietów SDK, które przyspieszają instrumentację i eksportowanie danych telemetrycznych (logów, wskaźników i śladów), które są wymagane w zakresie dostrzegalności. OpenTelemetry to projekt otwarty standardowo i prowadzony przez społeczność w ramach CNCF. Korzystając z bibliotek dostępnych w projekcie i jego ekosystemie, deweloperzy mogą dostosowywać swoje aplikacje w sposób neutralny od dostawcy i w związku z kilkoma architekturą.
Rozproszony log czasu
Śledzenie wśród logów, wskaźników i logów czasu to dane telemetryczne, które informują o czasie oczekiwania w określonej części procesu w systemie. Szczególnie w erze mikroserwisów rozproszony log czasu jest silnym czynnikiem wpływającym na wykrycie wąskich gardeł czasu oczekiwania w całym systemie rozproszonym.
Podczas analizowania rozproszonych logów czasu wizualizacja danych logu czasu ma kluczowe znaczenie dla szybkiego wychwytywania ogólnych opóźnień systemu. W rozproszonym logu czasu obsługujemy zbiór wywołań w celu przetworzenia pojedynczego żądania do punktu wejścia systemu w formie logu czasu zawierającego wiele spanów.
Rozpiętość reprezentuje pojedynczą jednostkę pracy wykonanej w systemie rozproszonym, rejestrując czasy rozpoczęcia i zatrzymania. Rozpiętości często są ułożone hierarchicznie między sobą – na poniższym obrazku wszystkie mniejsze rozpiętości to rozpiętości podrzędne dużego rozpiętości /messages i są połączone w jeden ślad, który pokazuje ścieżkę pracy w systemie.
Google Cloud Trace to jedna z opcji dla rozproszonego backendu logu czasu. Jest ona dobrze zintegrowana z innymi usługami Google Cloud.
Co utworzysz
W ramach tego ćwiczenia w Codelabs wykorzystasz dane śledzenia w usługach o nazwie „Shakesapp”. który działa w klastrze Kubernetes w Google Kubernetes Engine. Architektura Shakesapp:
- Klienty wysyłają ciąg zapytania do serwera
- Serwer akceptuje zapytanie od klienta, pobiera z Google Cloud Storage wszystkie dzieła Shakespare w formacie tekstowym, przeszukuje wiersze zawierające zapytanie i zwraca numer wiersza pasującego do klienta.
Dane z logu czasu będziesz modyfikować w żądaniu.
Czego się nauczysz
- Jak zacząć korzystać z bibliotek śledzenia OpenTelemetry w projekcie Pythona
- Jak utworzyć span za pomocą biblioteki
- Jak propagować konteksty spanów w obrębie przewodu między komponentami aplikacji
- Jak wysłać dane logu czasu do Google Cloud Trace
- Jak analizować log czasu w Google Cloud Trace
Z tego ćwiczenia w Codelabs dowiesz się, jak dostosować działanie mikroserwisów. Ten przykład zawiera tylko 3 komponenty (generator obciążenia, klient i serwer), ale w bardziej złożonych i dużych systemach można zastosować proces opisany w tym ćwiczeniu w Codelabs.
Czego potrzebujesz
- Wiedza na temat języka Python 3
2. Konfiguracja i wymagania
Samodzielne konfigurowanie środowiska
Jeśli nie masz jeszcze konta Google (w Gmailu lub Google Apps), musisz je utworzyć. Zaloguj się w konsoli Google Cloud Platform ( console.cloud.google.com) i utwórz nowy projekt.
Jeśli masz już projekt, kliknij menu wyboru projektu w lewym górnym rogu konsoli:
i kliknij „NOWY PROJEKT”. w wyświetlonym oknie, aby utworzyć nowy projekt:
Jeśli nie masz jeszcze projektu, zobaczysz takie okno dialogowe umożliwiające utworzenie pierwszego:
W kolejnym oknie tworzenia projektu możesz wpisać szczegóły nowego projektu:
Zapamiętaj identyfikator projektu, który jest niepowtarzalną nazwą we wszystkich projektach Google Cloud (powyższa nazwa jest już zajęta i nie będzie Ci odpowiadać). W dalszej części tego ćwiczenia z programowania będzie on określany jako PROJECT_ID.
Następnie musisz włączyć płatności w Developers Console, aby korzystać z zasobów Google Cloud i włączyć Cloud Trace API.
Wykonanie tych ćwiczeń w programie nie powinno kosztować więcej niż kilka dolarów, ale może być droższe, jeśli zdecydujesz się na więcej zasobów lub pozostawisz je włączone (patrz sekcja „Czyszczenie” na końcu tego dokumentu). Ceny Google Cloud Trace, Google Kubernetes Engine i Google Artifacat Registry podano w oficjalnej dokumentacji.
- Cennik Google Cloud Observability
- Ceny | Dokumentacja Kubernetes Engine
- Cennik Artifact Registry | Dokumentacja Artifact Registry
Nowi użytkownicy Google Cloud Platform mogą skorzystać z bezpłatnego okresu próbnego w wysokości 300 USD, dzięki czemu te ćwiczenia z programowania są całkowicie bezpłatne.
Konfiguracja Google Cloud Shell
Usługi Google Cloud i Google Cloud Trace można obsługiwać zdalnie z poziomu laptopa, ale w tym ćwiczeniu z programowania wykorzystamy Google Cloud Shell – środowisko wiersza poleceń działające w chmurze.
Ta maszyna wirtualna oparta na Debianie zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i uwierzytelnianie. Oznacza to, że do tego ćwiczenia z programowania wystarczy przeglądarka (tak, działa ona na Chromebooku).
Aby aktywować Cloud Shell z poziomu konsoli Cloud, kliknij Aktywuj Cloud Shell (udostępnienie środowiska i połączenie z nim powinno zająć tylko chwilę).
Po nawiązaniu połączenia z Cloud Shell powinno pojawić się potwierdzenie, że użytkownik jest już uwierzytelniony, a projekt jest już ustawiony na PROJECT_ID
.
gcloud auth list
Dane wyjściowe polecenia
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Dane wyjściowe polecenia
[core] project = <PROJECT_ID>
Jeśli z jakiegoś powodu projekt nie jest skonfigurowany, uruchom po prostu to polecenie:
gcloud config set project <PROJECT_ID>
Szukasz urządzenia PROJECT_ID
? Sprawdź identyfikator użyty w krokach konfiguracji lub wyszukaj go w panelu Cloud Console:
Cloud Shell ustawia też domyślnie niektóre zmienne środowiskowe, które mogą być przydatne podczas uruchamiania kolejnych poleceń.
echo $GOOGLE_CLOUD_PROJECT
Dane wyjściowe polecenia
<PROJECT_ID>
Na koniec ustaw domyślną strefę i konfigurację projektu.
gcloud config set compute/zone us-central1-f
Możesz wybrać różne strefy. Więcej informacji znajdziesz w artykule Regiony i Strefy.
Konfiguracja Pythona
W tym ćwiczeniu w Codelabs używamy słowa „poezja” aby ściśle zarządzać wersjami pakietów. Uruchom to polecenie w Cloud Shell:
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 - source $HOME/.poetry/env
Konfigurowanie klastra Google Kubernetes
W ramach tego ćwiczenia w Codelabs uruchomisz klaster mikroserwisów w Google Kubernetes Engine (GKE). Procedura w ramach ćwiczenia z programowania wygląda tak:
- Pobierz projekt bazowy do Cloud Shell
- Tworzenie mikroserwisów w kontenerach
- Przesyłanie kontenerów do Google Artifact Registry (GAR)
- Wdrażanie kontenerów w GKE
- Modyfikowanie kodu źródłowego usług na potrzeby narzędzi śledzenia
- Przejdź do kroku 2
Włączanie Kubernetes Engine
Najpierw skonfigurowaliśmy klaster Kubernetes, w którym aplikacja Shakesapp działa w GKE, więc musimy włączyć GKE. Przejdź do menu „Kubernetes Engine” i naciśnij przycisk WŁĄCZ.
Teraz możesz utworzyć klaster Kubernetes.
Tworzenie klastra Kubernetes
Aby utworzyć klaster Kubernetes, uruchom w Cloud Shell to polecenie. Upewnij się, że wartość strefy jest w regionie użytym do utworzenia repozytorium Artifact Registry. Zmień wartość strefy us-central1-f
, jeśli region repozytorium nie obejmuje tej strefy.
gcloud container clusters create otel-trace-codelab --zone us-central1-f \ --num-nodes 1 \ --machine-type e2-highcpu-4
Dane wyjściowe polecenia
Creating cluster otel-trace-codelab in us-central1-f... Cluster is being health-checked (master is healthy)...done. Created [https://container.googleapis.com/v1/projects/psychic-order-307806/zones/us-central1-f/clusters/otel-trace-codelab]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-f/otel-trace-codelab?project=psychic-order-307806 kubeconfig entry generated for otel-trace-codelab. NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS otel-trace-codelab us-central1-f 1.18.12-gke.1210 104.154.162.176 e2-medium 1.18.12-gke.1210 3 RUNNING
Konfiguracja Artifact Registry i skaffold
Klaster Kubernetes jest teraz gotowy do wdrożenia. W kolejnym kroku przygotujemy rejestr kontenerów do wypychania i wdrażania kontenerów. Na potrzeby tego kroku musimy skonfigurować narzędzie GAR i skaffold, aby z nich korzystać.
Konfiguracja Artifact Registry
Przejdź do menu „Artifact Registry” i naciśnij przycisk WŁĄCZ.
Po chwili zobaczysz przeglądarkę repozytoriów GAR. Kliknij „UTWÓRZ REPOZYTORIUM” i wpisz nazwę repozytorium.
W ramach tego ćwiczenia w Codelabs nadam nowemu repozytorium nazwę trace-codelab
. Format artefaktu to „Docker” a typ lokalizacji to „Region”. Wybierz region bliski temu, który został ustawiony dla domyślnej strefy Google Compute Engine. W tym przykładzie wybrano „us-central1-f”. powyżej, więc tutaj wybieramy „us-central1 (Iowa)”. Następnie kliknij przycisk „UTWÓRZ”, Przycisk
Teraz widzisz „trace-codelab”. w przeglądarce repozytoriów.
Wrócimy tu później, aby sprawdzić ścieżkę rejestru.
Konfiguracja Skaffold
Skaffold jest przydatnym narzędziem do tworzenia mikroserwisów działających w Kubernetes. Obsługuje przepływ pracy związany z tworzeniem, przekazywaniem i wdrażaniem kontenerów aplikacji za pomocą małego zestawu poleceń. Skaffold domyślnie używa Docker Registry jako rejestru kontenerów, dlatego musisz skonfigurować skaffold tak, aby rozpoznawał GAR przy przekazywaniu kontenerów do kontenerów.
Ponownie otwórz Cloud Shell i sprawdź, czy narzędzie skaffold jest zainstalowane. Cloud Shell domyślnie instaluje skaffold w środowisku. Uruchom następujące polecenie, aby wyświetlić wersję skaffold.
skaffold version
Dane wyjściowe polecenia
v1.20.0
Teraz możesz zarejestrować domyślne repozytorium, którego chcesz używać dla skaffold. Aby uzyskać ścieżkę rejestru, przejdź do panelu Artifact Registry i kliknij nazwę repozytorium utworzonego w poprzednim kroku.
Następnie na górze strony zobaczysz ścieżki menu nawigacyjnego. Kliknij ikonę , aby skopiować ścieżkę rejestru do schowka.
Po kliknięciu przycisku kopiowania na dole okna przeglądarki pojawi się okno z komunikatem takim jak:
"us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab" została skopiowana
Wróć do Cloud Shell. Uruchom polecenie skaffold config set default-repo
z wartością skopiowaną właśnie z panelu.
skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab
Dane wyjściowe polecenia
set value default-repo to us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab for context gke_stackdriver-sandbox-3438851889_us-central1-b_stackdriver-sandbox
Musisz też skonfigurować rejestr pod kątem konfiguracji Dockera. Uruchom to polecenie:
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
Dane wyjściowe polecenia
{ "credHelpers": { "gcr.io": "gcloud", "us.gcr.io": "gcloud", "eu.gcr.io": "gcloud", "asia.gcr.io": "gcloud", "staging-k8s.gcr.io": "gcloud", "marketplace.gcr.io": "gcloud", "us-central1-docker.pkg.dev": "gcloud" } } Adding credentials for: us-central1-docker.pkg.dev
Teraz możesz przejść do następnego kroku konfigurowania kontenera Kubernetes w GKE.
Podsumowanie
W tym kroku skonfigurujesz środowisko ćwiczeń z programowania:
- Konfigurowanie Cloud Shell
- Utworzono repozytorium Artifact Registy dla rejestru kontenerów
- Skonfiguruj skaffold, aby korzystać z rejestru kontenerów
- Utworzono klaster Kubernetes, w którym działają mikroserwisy ćwiczeń z programowania
Dalsze czynności
W następnym kroku skompilujesz, wypchniesz i wdrożysz mikroserwisy w klastrze
3. Tworzenie, przekazywanie i wdrażanie mikroserwisów
Pobierz materiały do ćwiczeń z programowania
W poprzednim kroku skonfigurowaliśmy wszystkie wymagania wstępne tego ćwiczenia z programowania. Teraz możesz uruchamiać na nich całe mikroserwisy. Materiały do ćwiczeń z programowania są hostowane na GitHubie, więc pobierz je do środowiska Cloud Shell za pomocą tego polecenia git.
cd ~ git clone https://github.com/GoogleCloudPlatform/opentelemetry-trace-codelab-python.git
Struktura katalogów projektu wygląda tak:
shakesapp-python ├── LICENSE ├── manifests │ ├── client.yaml │ ├── loadgen.yaml │ └── server.yaml ├── proto │ └── shakesapp.proto ├── skaffold.yaml └── src ├── client ├── loadgen └── server
- pliki manifestu: pliki manifestu Kubernetes.
- proto: definicja protokołu dla komunikacji między klientem a serwerem
- src: katalogi kodu źródłowego poszczególnych usług
- skaffold.yaml: plik konfiguracji dla skaffold
Uruchom polecenie skaffold
Możesz też zacząć kompilować, przenosić i wdrażać całe treści w utworzonym właśnie klastrze Kubernetes. Wygląda na to, że składa się z kilku kroków, ale w rzeczywistości skaffold robi wszystko za Ciebie. Spróbujmy to zrobić za pomocą tego polecenia:
cd shakesapp-python skaffold run --tail
Natychmiast po uruchomieniu polecenia zostaną wyświetlone dane wyjściowe dziennika docker build
i będziesz mieć pewność, że zostały one przekazane do rejestru.
Dane wyjściowe polecenia
... ---> Running in c39b3ea8692b ---> 90932a583ab6 Successfully built 90932a583ab6 Successfully tagged us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step1 The push refers to repository [us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice] cc8f5a05df4a: Preparing 5bf719419ee2: Preparing 2901929ad341: Preparing 88d9943798ba: Preparing b0fdf826a39a: Preparing 3c9c1e0b1647: Preparing f3427ce9393d: Preparing 14a1ca976738: Preparing f3427ce9393d: Waiting 14a1ca976738: Waiting 3c9c1e0b1647: Waiting b0fdf826a39a: Layer already exists 88d9943798ba: Layer already exists f3427ce9393d: Layer already exists 3c9c1e0b1647: Layer already exists 14a1ca976738: Layer already exists 2901929ad341: Pushed 5bf719419ee2: Pushed cc8f5a05df4a: Pushed step1: digest: sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe size: 2001
Po przekazaniu wszystkich kontenerów usługi wdrożenia Kubernetes uruchamiają się automatycznie.
Dane wyjściowe polecenia
sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8 size: 1997 Tags used in deployment: - serverservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step4@sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe - clientservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/clientservice:step4@sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8 - loadgen -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/loadgen:step4@sha256:eea2e5bc8463ecf886f958a86906cab896e9e2e380a0eb143deaeaca40f7888a Starting deploy... - deployment.apps/clientservice created - service/clientservice created - deployment.apps/loadgen created - deployment.apps/serverservice created - service/serverservice created
Uwaga: jeśli pojawi się błąd taki jak „Brak dostępu push do określonego repozytorium obrazów”, sprawdź, czy polecenie skaffold próbuje przekazać obrazy do Docker Hub (docker.io) niezależnie od konfiguracji w domyślnym repozytorium w skaffold. W takim przypadku spróbuj dodać „–default-repo” opcja „skaffold run” jak poniżej.
$ skaffold run –tail –default-repo=us-central1-docker.pkg.dev/[identyfikator projektu]/[nazwa repozytorium]
Po wdrożeniu zobaczysz rzeczywiste logi aplikacji wysyłane do stdout w poszczególnych kontenerach w następujący sposób:
Dane wyjściowe polecenia
[server] {"event": "starting server: 0.0.0.0:5050", "severity": "info", "timestamp": "2021-03-17T05:25:56.758575Z"} [client] [2021-03-17 05:25:54 +0000] [1] [INFO] Starting gunicorn 20.0.4 [client] [2021-03-17 05:25:54 +0000] [1] [INFO] Listening at: http://0.0.0.0:8080 (1) [client] [2021-03-17 05:25:54 +0000] [1] [INFO] Using worker: threads [client] [2021-03-17 05:25:54 +0000] [7] [INFO] Booting worker with pid: 7 [client] {"event": "server address is serverservice:5050", "severity": "info", "timestamp": "2021-03-17T05:25:54.888627Z"} [client] {"event": "request to server with query: world", "severity": "info", "timestamp": "2021-03-17T05:26:11.550923Z"} [server] {"event": "query: world", "severity": "info", "timestamp": "2021-03-17T05:26:11.567048Z"} [loadgen] {"event": "check connectivity: http://clientservice:8080/_healthz", "severity": "info", "timestamp": "2021-03-17T05:26:11.533605Z"} [loadgen] {"event": "/_healthz response: ok", "severity": "info", "timestamp": "2021-03-17T05:26:11.544267Z"} [loadgen] {"event": "confirmed connection ot clientservice", "severity": "info", "timestamp": "2021-03-17T05:26:11.544527Z"}
Możesz też zacząć instrumentować swoją aplikację za pomocą OpenTelemetry do rozproszonego śledzenia usług.
Podsumowanie
Na tym etapie masz już przygotowane materiały z ćwiczeń z programowania w swoim środowisku oraz potwierdzone uruchomienia skaffold zgodnie z oczekiwaniami.
Dalsze czynności
W następnym kroku zmodyfikujesz kod źródłowy usługi loadgen, aby dostosować dane śledzenia.
4. Narzędzia dla HTTP
Koncepcja narzędzi do śledzenia i rozpowszechniania
Przed edycją kodu źródłowego omówię pokrótce, jak działają rozproszone logi czasu na prostym diagramie.
W tym przykładzie opracowujemy kod do eksportowania informacji logu czasu i spanu do Cloud Trace oraz rozpowszechniania kontekstu logu czasu w żądaniu z usługi Loadgen do usługi serwera.
Aplikacja musi wysłać metadane logu czasu, takie jak identyfikator logu czasu i identyfikator spanu, aby w Cloud Trace zebrać wszystkie spany o tym samym identyfikatorze logu czasu w jednym logu czasu. Aplikacja musi też rozpowszechniać konteksty logu czasu (kombinację identyfikatora logu czasu i identyfikatora spanu spanu nadrzędnego) przy wysyłaniu żądań usług podrzędnych, aby wiedziały, którego kontekstu śledzenia obsługują.
OpenTelemetry pomaga:
- do wygenerowania unikalnego identyfikatora logu czasu i identyfikatora spanu
- do wyeksportowania identyfikatora logu czasu i identyfikatora spanu do backendu
- do rozpowszechniania kontekstu logu czasu w innych usługach
Instrument – pierwszy span
Usługa generatora obciążenia instrumentu
Otwórz edytor Cloud Shell, naciskając przycisk w prawym górnym rogu Cloud Shell. Otwórz
src/loadgen/loadgen.py
w eksploratorze w panelu po lewej stronie i znajdź funkcję main
.
src/loadgen/loadgen.py
def main():
...
# start request loop to client service
logger.info("start client request loop")
addr = f"http://{target}"
while True:
logger.info("start request to client")
call_client(addr)
logger.info("end request to client")
time.sleep(2.0)
W funkcji main
widzisz pętlę wywołującą w niej funkcję call_client
. W bieżącej implementacji sektoin ma 2 wiersze logu, które rejestrują początek i koniec wywołania funkcji. Teraz zastosujmy informacje o spanie, aby śledzić opóźnienie wywołania funkcji.
Najpierw musisz utworzyć span z unikalnym identyfikatorem logu czasu i identyfikatorem spanu. OpenTelemetry ma przydatną bibliotekę. Dodaj poniższe wiersze, aby zaimportować biblioteki OpenTelemetry do kodu.
import structlog
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.instrumentation.requests import RequestsInstrumentor
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
Ponieważ generator obciążenia wywołuje aplikację kliencką w formacie HTTP przez moduł requests
, używamy pakietu rozszerzeń dla interfejsu requests
i włączamy narzędzia.
from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
+
+RequestsInstrumentor().instrument()
Następnie skonfiguruj instancję usługi Trace, która obsługuje ustawienia funkcji Trace Contenxt i eksportera.
target = os.environ.get("CLIENT_ADDR", "0.0.0.0:8080")
+ exporter = CloudTraceSpanExporter()
+ trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))
+ tracer = trace.get_tracer(__name__)
+ propagate.set_global_textmap(CloudTraceFormatPropagator())
+ trace.set_tracer_provider(TracerProvider())
+
# connectivity check to client service
healthz = f"http://{target}/_healthz"
logger.info(f"check connectivity: {healthz}")
Pamiętaj, że jest to ćwiczenie w Codelabs, które pozwala zrozumieć, jak działa instrumentacja logów czasu, więc konfigurujemy lokalizator tak, aby rejestrował każde żądanie i wysyłał je do backendu. (SimpleSpanProcessor()
) Nie pasuje do środowisk produkcyjnych, więc pamiętaj, aby zmienić tę część podczas przystosowywania aplikacji produkcyjnej.
Teraz możesz instrumentować spany za pomocą lokalizatora. Chodzi o to, aby samodzielnie wygenerować span. To wszystko. Chociaż do spanu dodano 2 wiersze metadanych zdarzeń, nie musisz ręcznie generować unikalnego identyfikatora logu czasu i identyfikatora spanu ani umieszczać ich w spanie.
logger.info("start client request loop")
addr = f"http://{target}"
while True:
- logger.info("start request to client")
- call_client(addr)
- logger.info("end request to client")
+ with tracer.start_as_current_span("loadgen") as root_span:
+ root_span.add_event(name="request_start")
+ logger.info("start request to client")
+ call_client(addr)
+ root_span.add_event(name="request_end")
+ logger.info("end request to client")
time.sleep(2.0)
Aby kompilacja Dockera pobrała wymagane pakiety OpenTelemetry, uruchom to polecenie:
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation-requests=^0.20b0"
Możesz potwierdzić, że odpowiedni opis zależności jest zapisany w języku pyproject.toml
.
Dostosowywanie działania usługi klienckiej
W poprzedniej sekcji opracowaliśmy numer części zawartej w czerwonym prostokącie na rysunku poniżej. Informacje o spanach zostały skonfigurowane w usłudze generatora obciążenia. Podobnie jak w przypadku generatora obciążenia, teraz musimy dostosować obsługę klienta. Różnica w stosunku do usługi generatora obciążenia polega na tym, że usługa kliencka musi wyodrębniać informacje o identyfikatorach śledzenia przekazywane z usługi generatora obciążenia w nagłówku HTTP i używać tego identyfikatora do generowania zakresów.
Otwórz edytor Cloud Shell i dodaj wymagane moduły, tak jak w przypadku usługi generatora obciążenia.
src/client/client.py
import flask
import grpc
import structlog
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.instrumentation.flask import FlaskInstrumentor
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import \
+ CloudTraceFormatPropagator
import shakesapp_pb2
import shakesapp_pb2_grpc
Zauważasz, że przed chwilą zaimportowano plik FlaskInstrumentor
, który umożliwia automatyczną instrumentację aplikacji Flask w imieniu użytkowników na wyodrębnianie nagłówków HTTP w celu uzyskania kontekstów logu czasu za pomocą 1 wiersza kodu. Społeczność OpenTelemetry oferuje podobne przydatne integracje z innymi popularnymi bibliotekami. Więcej informacji znajdziesz w oficjalnej dokumentacji.
app = flask.Flask(__name__)
+FlaskInstrumentor().instrument_app(app)
Przed rozpoczęciem instrumentacji musisz przygotować instancję Tracer, podobnie jak w usłudze generatora obciążenia.
logger.info(f"server address is {SERVER_ADDR}")
+exporter = CloudTraceSpanExporter()
+trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))
+propagate.set_global_textmap(CloudTraceFormatPropagator())
+trace.set_tracer_provider(TracerProvider())
@app.route("/")
def main_handler():
....
Teraz można dodać instrumentację do modułu obsługi. Znajdź element main_handler()
i zmodyfikuj część, która wysyła żądanie gRPC do usługi serwera.
@app.route("/")
def main_handler():
q, count = random.choice(list(queries.items()))
# get Tracer
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("client") as cur_span:
channel = grpc.insecure_channel(SERVER_ADDR)
stub = shakesapp_pb2_grpc.ShakespeareServiceStub(channel)
logger.info(f"request to server with query: {q}")
cur_span.add_event("server_call_start")
resp = stub.GetMatchCount(shakesapp_pb2.ShakespeareRequest(query=q))
cur_span.add_event("server_call_end")
if count != resp.match_count:
raise UnexpectedResultError(
f"The expected count for '{q}' was {count}, but result was {resp.match_count } obtained"
)
result = str(resp.match_count)
logger.info(f"matched count for '{q}' is {result}")
return result
Podobnie jak w przypadku usługi generatora dodaj wymagane pakiety do pyproject.toml
za pomocą tego polecenia.
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation-flask=^0.20b0"
Następnie spróbuj uruchomić aplikację za pomocą polecenia skaffold run
i zobacz, co pokazuje panel Cloud Trace:
skaffold run --tail
Po wyświetleniu wiadomości dotyczących kompilacji, wypychania i wdrażania zobaczysz logi aplikacji w formacie JSON. Przejdź do Cloud Trace > Lista logów czasu, aby sprawdzić, czy otrzymujesz informacje z logów czasu. Ponieważ usługa generatora obciążenia wysyła żądania do usługi klienta okresowo, a dla wszystkich żądań masz włączone logi czasu, na liście logów czasu pojawi się wiele kropek.
Gdy klikniesz jeden z nich, zobaczysz wykres kaskadowy widoczny poniżej, który wyjaśnia czas oczekiwania w każdej części procesu żądania i odpowiedzi. Zaznacz pole wyboru obok opcji „Pokaż zdarzenia”, aby wyświetlić adnotacje na wykresie kaskadowym. Są to adnotacje, które zostały stworzone w kodzie za pomocą metody span.add_event()
.
Możesz zauważyć, że nie widzisz spanów z usługi serwera. To jest poprawna odpowiedź, ponieważ w usłudze serwera nie z instrumentalizowaliśmy żadnych Spansów.
Podsumowanie
W tym kroku udało Ci się wdrożyć usługę generatora obciążenia i usługę klienta oraz potwierdzić, że udało Ci się rozpowszechnić kontekst logu czasu między usługami i wyeksportować informacje spanu z obu usług do Cloud Trace.
Dalsze czynności
W następnym kroku zaimplementujesz usługę klienta i usługę serwera, aby potwierdzić sposób rozpowszechnienia kontekstu śledzenia za pomocą gRPC.
5. Narzędzia dla gRPC
W poprzednim kroku zdefiniowaliśmy pierwszą połowę żądania w tych mikroserwisach. Na tym etapie próbujemy instrumentować komunikację gRPC między usługą klienta a usługą serwera. (Zielony i fioletowy prostokąt na ilustracji poniżej)
Automatyczna instrumentacja dla klienta gRPC
Ekosystem OpenTelemetry zawiera wiele przydatnych bibliotek, które ułatwiają programistom dostosowywanie aplikacji. W poprzednim kroku użyliśmy automatycznej instrumentacji dla „żądań” . Na tym etapie, gdy próbujemy przekazać kontekst logu czasu za pomocą gRPC, użyjemy do tego biblioteki.
src/client/client.py
import flask
import grpc
import structlog
from opentelemetry import propagate, trace
from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
from opentelemetry.instrumentation.flask import FlaskInstrumentor
+from opentelemetry.instrumentation.grpc import GrpcInstrumentorClient
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor
from opentelemetry.propagators.cloud_trace_propagator import \
CloudTraceFormatPropagator
import shakesapp_pb2
import shakesapp_pb2_grpc
app = flask.Flask(__name__)
FlaskInstrumentor().instrument_app(app)
+GrpcInstrumentorClient().instrument()
W przypadku obsługi klienta nakłady inwestycyjne są naprawdę niewielkie. Chcemy przekazać kontekst logu czasu, który jest kombinacją identyfikatora logu czasu i identyfikatora spanu bieżącego spanu w gRPC. Wywołujemy więc GrpcInstrumentatorClient.instrument()
, aby klient gRPC w funkcji obsługi mógł osadzić kontekst logu czasu w nagłówku HTTP znajdującym się poniżej.
Pamiętaj, aby dodać nowe zależności do zasady pyproject.toml
za pomocą polecenia poetry add
:
poetry add "opentelemetry-instrumentation-grpc=^0.20b0"
Automatyczna instrumentacja dla serwera gRPC
Podobnie jak w przypadku klienta gRPC, dla serwera gRPC nazywamy automatyczną instrumentację. Dodaj importy takie jak obserwowane i wywołaj GrpcInstrumentationServer().instrument()
na początku pliku.
Uwaga: pamiętaj, by zadzwonić
GrpcInstrumentationServe()
w tym kroku, a nie
GrpcInstrumentationClient()
.
src/server/server.py
import grpc
import structlog
from google.cloud import storage
from grpc_health.v1 import health_pb2, health_pb2_grpc
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
import shakesapp_pb2
import shakesapp_pb2_grpc
BUCKET_NAME = "dataflow-samples"
BUCKET_PREFIX = "shakespeare/"
+# enable auto gRPC server trace instrumentation
+GrpcInstrumentorServer().instrument()
+
Dodaj eksportera, aby wysłać informacje logu czasu do backendu Cloud Trace. Dodaj poniższy kod do funkcji serve()
.
def serve():
+ # start trace exporter
+ trace.set_tracer_provider(TracerProvider())
+ trace.get_tracer_provider().add_span_processor(
+ SimpleSpanProcessor(CloudTraceSpanExporter())
+ )
+ propagators.set_global_textmap(CloudTraceFormatPropagator())
+
+ # add gRPC services to server
server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
service = ShakesappService()
shakesapp_pb2_grpc.add_ShakespeareServiceServicer_to_server(service, server)
health_pb2_grpc.add_HealthServicer_to_server(service, server)
Pamiętaj, aby dodać nowo dodane pakiety w usłudze serwera.
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-instrumentation-grpc=^0.20b0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation=^0.20b0"
Uruchamianie mikroserwisu i potwierdzenie śledzenia
Następnie uruchom zmodyfikowany kod za pomocą polecenia skaffold.
skaffold run --tail
Teraz ponownie widzisz kilka logów czasu na stronie z listą logów czasu Cloud Trace. Kliknij jeden ze logów czasu i zauważysz, że obejmuje on żądanie od usługi generatora obciążenia do usługi serwera.
Podsumowanie
W tym kroku zinstrumentowaliśmy komunikację opartą na gRPC przy użyciu bibliotek ekosystemu OpenTelemetry. Udało Ci się też potwierdzić, że kontekst logu czasu wygenerowany w usłudze generatora obciążenia został przesłany do usługi serwera.
6. Gratulacje
Udało Ci się utworzyć rozproszone logi czasu przy użyciu OpenTelemery i potwierdzone opóźnienia żądań w mikroserwisie w Google Cloud Trace.
W przypadku dłuższych ćwiczeń możesz samodzielnie wypróbować poniższe tematy.
- Obecna implementacja wysyła wszystkie spany wygenerowane przez kontrolę stanu. Jak można odfiltrować te spany z Cloud Traces? Wskazówka znajdziesz tutaj.
- Skoreluj logi zdarzeń ze spanami i sprawdź, jak działa to w Google Cloud Trace i Google Cloud Logging. Wskazówka znajdziesz tutaj.
- Zastąp jakąś usługę usługą w innym języku i spróbuj skonfigurować ją za pomocą OpenTelemetry dla tego języka.
Uwaga: Google Kubernetes Engine i Google Artifact Registry nieustannie zużywają zasób.
Czyszczenie danych
Po ukończeniu tego ćwiczenia w Codelabs zatrzymaj klaster Kubernetes i pamiętaj o usunięciu projektu, aby nie otrzymywać nieoczekiwanych opłat w Google Kubernetes Engine, Google Cloud Trace czy Google Artifact Registry.
Najpierw usuń klaster za pomocą tego polecenia:
skaffold delete
Dane wyjściowe polecenia
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
Po usunięciu klastra w panelu menu wybierz „Uprawnienia Administrator > „Ustawienia”, a następnie kliknij „WYŁĄCZ” Przycisk
Następnie wpisz identyfikator projektu (nie nazwę projektu) w formularzu w oknie i potwierdź zamknięcie.