1. Введение
Последнее обновление: 5 марта 2021 г.
Наблюдаемость приложения
Наблюдаемость и OpenTelemetry
Наблюдаемость — это термин, используемый для описания атрибута системы. Система с возможностью наблюдения позволяет командам активно отлаживать свою систему. В этом контексте три столпа наблюдаемости; журналы, метрики и трассировки — это фундаментальные инструменты, позволяющие системе обеспечить наблюдаемость.
OpenTelemetry — это набор спецификаций и пакетов SDK, которые ускоряют инструментирование и экспорт данных телеметрии (журналы, метрики и трассировки), необходимых для наблюдения. OpenTelemetry — это проект открытого стандарта, управляемый сообществом под эгидой CNCF. Используя библиотеки, предоставляемые проектом и его экосистемой, разработчики могут инструментировать свои приложения независимо от поставщика и с учетом различных архитектур.
Распределенная трассировка
Среди журналов, метрик и трассировок трассировка — это телеметрия, которая сообщает о задержке определенной части процесса в системе. Особенно в эпоху микросервисов распределенная трассировка является сильным стимулом для выявления узких мест задержки во всей распределенной системе.
При анализе распределенных трассировок визуализация данных трассировки является ключом к быстрому определению общих задержек системы. В распределенной трассировке мы обрабатываем набор вызовов для обработки одного запроса к точке входа в систему в форме трассировки, содержащей несколько промежутков.
Промежуток представляет собой отдельную единицу работы, выполняемую в распределенной системе, с записью времени начала и остановки. Промежутки часто имеют иерархические отношения между собой — на рисунке ниже все меньшие промежутки являются дочерними промежутками большого промежутка /messages и собраны в одну трассировку, которая показывает путь работы через систему.
Google Cloud Trace — это один из вариантов распределенной серверной части трассировки, который хорошо интегрируется с другими продуктами в Google Cloud.
Что ты построишь
В этой лаборатории кода вы собираетесь инструментировать информацию трассировки в службах под названием Shakesapp, которые работают в кластере Kubernetes, работающем на Google Kubernetes Engine. Архитектура Shakesapp описана ниже:
- Клиенты отправляют строку запроса на сервер
- Сервер принимает запрос от клиента, извлекает все произведения Шекспира в текстовом формате из Google Cloud Storage, ищет строки, содержащие запрос, и возвращает номер строки, совпадающей с клиентом.
Вы будете инструментировать информацию трассировки по всему запросу.
Что вы узнаете
- Как начать работу с библиотеками OpenTelemetry Trace в проекте Python
- Как создать диапазон с помощью библиотеки
- Как передавать контексты диапазона по сети между компонентами приложения
- Как отправить данные трассировки в Google Cloud Trace
- Как проанализировать трассировку в Google Cloud Trace
В этой кодовой лаборатории объясняется, как инструментировать ваши микросервисы. Чтобы упростить понимание, этот пример содержит только 3 компонента (генератор нагрузки, клиент и сервер), но вы можете применить тот же процесс, описанный в этой кодовой лаборатории, к более сложным и большим системам.
Что вам понадобится
- Знание Python 3.
2. Настройка и требования
Самостоятельная настройка среды
Если у вас еще нет учетной записи Google (Gmail или Google Apps), вам необходимо ее создать . Войдите в консоль Google Cloud Platform ( console.cloud.google.com ) и создайте новый проект.
Если у вас уже есть проект, щелкните раскрывающееся меню выбора проекта в левом верхнем углу консоли:
и нажмите кнопку «НОВЫЙ ПРОЕКТ» в появившемся диалоговом окне, чтобы создать новый проект:
Если у вас еще нет проекта, вы должны увидеть подобное диалоговое окно, чтобы создать свой первый:
Последующий диалог создания проекта позволяет вам ввести детали вашего нового проекта:
Запомните идентификатор проекта, который является уникальным именем для всех проектов Google Cloud (имя, указанное выше, уже занято и не подойдет вам, извините!). Позже в этой лаборатории он будет называться PROJECT_ID.
Далее, если вы еще этого не сделали, вам необходимо включить выставление счетов в консоли разработчика, чтобы использовать ресурсы Google Cloud и включить Cloud Trace API .
Выполнение этой кодовой лаборатории не должно стоить вам больше нескольких долларов, но может стоить больше, если вы решите использовать больше ресурсов или оставите их включенными (см. раздел «Очистка» в конце этого документа). Цены на Google Cloud Trace, Google Kubernetes Engine и реестр Google Artifacat указаны в официальной документации.
- Цены на Google Cloud Observability
- Цены | Документация по движку Kubernetes
- Цены на реестр артефактов | Документация по реестру артефактов
Новые пользователи Google Cloud Platform имеют право на бесплатную пробную версию за 300 долларов США , что делает эту лабораторию кода совершенно бесплатной.
Настройка Google Cloud Shell
Хотя Google Cloud и Google Cloud Trace можно управлять удаленно с вашего ноутбука, в этой лаборатории мы будем использовать Google Cloud Shell , среду командной строки, работающую в облаке.
Эта виртуальная машина на базе Debian оснащена всеми необходимыми инструментами разработки. Он предлагает постоянный домашний каталог объемом 5 ГБ и работает в Google Cloud, что значительно повышает производительность сети и аутентификацию. Это означает, что все, что вам понадобится для этой лаборатории кода, — это браузер (да, он работает на Chromebook).
Чтобы активировать Cloud Shell из Cloud Console, просто нажмите «Активировать Cloud Shell». (подготовка и подключение к среде займет всего несколько минут).
После подключения к Cloud Shell вы увидите, что вы уже прошли аутентификацию и что для проекта уже установлен ваш PROJECT_ID
.
gcloud auth list
Вывод команды
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Вывод команды
[core] project = <PROJECT_ID>
Если по какой-то причине проект не установлен, просто введите следующую команду:
gcloud config set project <PROJECT_ID>
Ищете свой PROJECT_ID
? Узнайте, какой идентификатор вы использовали на этапах настройки, или найдите его на панели управления Cloud Console:
Cloud Shell также по умолчанию устанавливает некоторые переменные среды, которые могут быть полезны при выполнении будущих команд.
echo $GOOGLE_CLOUD_PROJECT
Выход команды
<PROJECT_ID>
Наконец, установите зону по умолчанию и конфигурацию проекта.
gcloud config set compute/zone us-central1-f
Вы можете выбрать множество различных зон. Дополнительную информацию см. в разделе «Регионы и зоны» .
Настройка Python
В этой кодовой лаборатории мы используем «поэзию» для строгого управления версиями пакетов. Выполните следующую команду в Cloud Shell:
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 - source $HOME/.poetry/env
Настройка кластера Google Kubernetes
В этой лаборатории кода вы запустите кластер микросервисов в Google Kubernetes Engine (GKE). Процесс этой кодовой лаборатории выглядит следующим образом:
- Загрузите базовый проект в Cloud Shell.
- Встраивайте микросервисы в контейнеры
- Загрузите контейнеры в реестр артефактов Google (GAR).
- Развертывание контейнеров в GKE
- Измените исходный код служб для инструментов трассировки.
- Перейти к шагу 2
Включить движок Kubernetes
Сначала мы настраиваем кластер Kubernetes, в котором Shakesapp работает на GKE, поэтому нам нужно включить GKE. Перейдите в меню «Kubernetes Engine» и нажмите кнопку ВКЛЮЧИТЬ.
Теперь вы готовы создать кластер Kubernetes.
Создать кластер Kubernetes
В Cloud Shell выполните следующую команду, чтобы создать кластер Kubernetes. Подтвердите, что значение зоны соответствует региону , который вы использовали для создания репозитория реестра артефактов. Измените значение зоны us-central1-f
если регион вашего репозитория не охватывает эту зону.
gcloud container clusters create otel-trace-codelab --zone us-central1-f \ --num-nodes 1 \ --machine-type e2-highcpu-4
Вывод команды
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
Реестр артефактов и настройка скаффолда
Теперь у нас есть кластер Kubernetes, готовый к развертыванию. Затем мы готовим реестр контейнеров для отправки и развертывания контейнеров. Для этого шага нам нужно настроить GAR и скаффолд для его использования.
Настройка реестра артефактов
Перейдите в меню «Реестр артефактов» и нажмите кнопку ВКЛЮЧИТЬ.
Через несколько секунд вы увидите браузер репозитория GAR. Нажмите кнопку «СОЗДАТЬ РЕПОЗИТОРИЙ» и введите имя репозитория.
В этой кодовой лаборатории я называю новый репозиторий trace-codelab
. Формат артефакта — «Docker», а тип местоположения — «Регион». Выберите регион, близкий к тому, который вы установили для зоны по умолчанию Google Compute Engine. Например, в этом примере выше выбрано «us-central1-f», поэтому здесь мы выбираем «us-central1 (Айова)». Затем нажмите кнопку «СОЗДАТЬ».
Теперь вы видите «trace-codelab» в браузере репозитория.
Мы вернемся сюда позже, чтобы проверить путь к реестру.
Установка строительных лесов
Skaffold — удобный инструмент, когда вы работаете над созданием микросервисов, работающих в Kubernetes. Он управляет рабочим процессом создания, отправки и развертывания контейнеров приложений с помощью небольшого набора команд. Skaffold по умолчанию использует реестр Docker в качестве реестра контейнеров, поэтому вам необходимо настроить skaffold для распознавания GAR при отправке контейнеров.
Снова откройте Cloud Shell и убедитесь, что skaffold установлен. (Cloud Shell по умолчанию устанавливает скаффолд в среду.) Выполните следующую команду и посмотрите версию скаффолда.
skaffold version
Вывод команды
v1.20.0
Теперь вы можете зарегистрировать репозиторий по умолчанию для использования скаффолдом. Чтобы получить путь к реестру, перейдите на панель мониторинга реестра артефактов и щелкните имя репозитория, который вы только что настроили на предыдущем шаге.
Затем вы увидите следы хлебных крошек в верхней части страницы. Нажмите значок, чтобы скопировать путь реестра в буфер обмена.
При нажатии кнопки копирования вы увидите диалоговое окно в нижней части браузера с сообщением типа:
«us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab» скопирован.
Вернитесь в облачную оболочку. Запустите команду skaffold config set default-repo
со значением, которое вы только что скопировали с панели управления.
skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab
Вывод команды
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
Кроме того, вам необходимо настроить реестр в соответствии с конфигурацией Docker. Выполните следующую команду:
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
Вывод команды
{ "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
Теперь можно перейти к следующему шагу — настройке контейнера Kubernetes в GKE.
Краткое содержание
На этом этапе вы настраиваете среду кодовой лаборатории:
- Настройте Cloud Shell
- Создан репозиторий Artifact Registy для реестра контейнеров.
- Настройте skaffold для использования реестра контейнеров.
- Создан кластер Kubernetes, в котором работают микросервисы Codelab.
Дальше
На следующем этапе вы создадите, отправите и развернете свои микросервисы в кластере.
3. Создавайте, распространяйте и развертывайте микросервисы.
Загрузите материал codelab
На предыдущем шаге мы создали все необходимые условия для этой лаборатории кода. Теперь вы готовы запускать поверх них целые микросервисы. Материалы Codelab размещены на GitHub, поэтому загрузите их в среду Cloud Shell с помощью следующей команды git.
cd ~ git clone https://github.com/GoogleCloudPlatform/opentelemetry-trace-codelab-python.git
Структура каталогов проекта следующая:
shakesapp-python ├── LICENSE ├── manifests │ ├── client.yaml │ ├── loadgen.yaml │ └── server.yaml ├── proto │ └── shakesapp.proto ├── skaffold.yaml └── src ├── client ├── loadgen └── server
- манифесты: файлы манифеста Kubernetes.
- proto: определение протокола для связи между клиентом и сервером.
- src: каталоги с исходным кодом каждого сервиса.
- skaffold.yaml: файл конфигурации для skaffold.
Запустить команду скаффолда
Наконец, вы готовы собирать, отправлять и развертывать весь контент в только что созданном кластере Kubernetes. Кажется, что это несколько шагов, но на самом деле skaffold делает все за вас. Давайте попробуем это с помощью следующей команды:
cd shakesapp-python skaffold run --tail
Как только вы запустите команду, вы увидите выходные данные журнала docker build
и сможете подтвердить, что они успешно отправлены в реестр.
Вывод команды
... ---> 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
После отправки всех сервисных контейнеров развертывание Kubernetes запускается автоматически.
Вывод команды
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
Внимание ! Если вы получаете сообщение об ошибке типа «Нет принудительного доступа к указанному репозиторию изображений», проверьте, пытается ли команда skaffold отправить изображения в Docker Hub (docker.io) независимо от вашей конфигурации в репозитории по умолчанию в skaffold. В этом случае попробуйте добавить параметр «–default-repo» к «запуску скаффолда», как показано ниже.
$ skaffold run –tail –default-repo=us-central1-docker.pkg.dev/[ID проекта]/[имя репозитория]
После развертывания вы увидите фактические журналы приложений, отправляемые на стандартный вывод в каждом контейнере, например:
Вывод команды
[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"}
Наконец, вы готовы приступить к оснащению своего приложения OpenTelemetry для распределенной трассировки служб.
Краткое содержание
На этом этапе вы подготовили материал codelab в своей среде и подтвердили ожидаемое выполнение скаффолда.
Дальше
На следующем шаге вы измените исходный код службы loadgen для инструментирования информации трассировки.
4. Инструментарий для HTTP
Концепция инструментирования и распространения трассировки
Прежде чем редактировать исходный код, позвольте мне кратко объяснить, как работают распределенные трассировки, на простой диаграмме.
В этом примере мы используем код для экспорта информации Trace и Span в Cloud Trace и распространения контекста трассировки по запросу от службы Loadgen к серверной службе.
Приложению необходимо отправлять метаданные трассировки, такие как идентификатор трассировки и идентификатор интервала, чтобы Cloud Trace мог объединить все интервалы с одинаковым идентификатором трассировки в одну трассировку. Кроме того, приложению необходимо распространять контексты трассировки (комбинацию идентификатора трассировки и идентификатора диапазона родительского диапазона) при запросе нижестоящих служб, чтобы они могли знать, какой контекст трассировки они обрабатывают.
OpenTelemetry поможет вам:
- для создания уникального идентификатора трассировки и идентификатора диапазона
- для экспорта идентификатора трассировки и идентификатора диапазона на серверную часть
- для распространения контекстов трассировки на другие службы
Первый диапазон прибора
Сервис генератора инструментальной нагрузки
Откройте редактор Cloud Shell, нажав кнопку в правом верхнем углу Cloud Shell. Откройте src/loadgen/loadgen.py
из проводника на левой панели и найдите 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)
В main
функции вы видите цикл, вызывающий в нем функцию call_client
. В текущей реализации сектоин имеет 2 строки журнала, в которых фиксируется начало и окончание вызова функции. Теперь давайте инструментируем информацию Span для отслеживания задержки вызова функции.
Во-первых, вам необходимо создать диапазон с уникальным идентификатором трассировки и идентификатором диапазона. OpenTelemetry предоставляет для этого удобную библиотеку. Добавьте следующие строки, чтобы импортировать библиотеки OpenTelemetry в свой код.
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
Поскольку генератор нагрузки вызывает клиентское приложение по HTTP через модуль requests
, мы используем пакет расширения для requests
и включаем инструментирование.
from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
+
+RequestsInstrumentor().instrument()
Затем настройте экземпляр Tracer, который обрабатывает Trace Contenxt и настройки экспортера.
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}")
Обратите внимание: поскольку это лабораторная работа, позволяющая понять, как работает инструментарий трассировки, мы настраиваем Tracer для записи каждого отдельного запроса и отправки его на серверную часть. ( SimpleSpanProcessor()
) Это не подходит для производственных сред, поэтому обязательно измените эту часть при инструментировании рабочего приложения.
Теперь вы можете инструментировать промежутки с помощью Tracer. Дело в том, что вам нужно явно сгенерировать Span, и все! Хотя есть две строки, которые добавляют метаданные событий в Span, вам не нужно вручную генерировать уникальные идентификаторы Trace ID и Span ID и встраивать их в Span.
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)
Чтобы сборка Docker извлекла необходимые пакеты OpenTelemetry, выполните следующую команду:
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation-requests=^0.20b0"
Вы можете убедиться, что соответствующее описание зависимости записано в pyproject.toml
.
Клиентское обслуживание инструментов
В предыдущем разделе мы обработали деталь, обведенную красным прямоугольником на рисунке ниже. Мы инструментировали информацию о диапазоне в службе генератора нагрузки. Как и в случае со службой генератора нагрузки, теперь нам нужно инструментировать клиентскую службу. Отличие от службы генератора нагрузки заключается в том, что клиентской службе необходимо извлечь информацию Trace ID, передаваемую из службы генератора нагрузки, в заголовок HTTP, и использовать этот идентификатор для создания интервалов.
Откройте редактор Cloud Shell и добавьте необходимые модули, как мы это сделали для службы генератора нагрузки.
источник/клиент/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
Вы заметили, что только что импортировали FlaskInstrumentor
, который позволяет автоматизировать инструментирование приложения Flask от имени пользователей для извлечения заголовков HTTP для получения контекстов трассировки с помощью одной строки кода. Сообщество OpenTelemetry предоставляет аналогичные полезные интеграции с другими крупными библиотеками. Для получения дополнительной информации вы можете обратиться к официальной документации .
app = flask.Flask(__name__)
+FlaskInstrumentor().instrument_app(app)
Перед запуском инструментирования вам снова необходимо подготовить экземпляр Tracer аналогично тому, что мы делали в сервисе генератора нагрузки.
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():
....
Теперь все готово для добавления инструментов в обработчик. Найдите main_handler()
и измените часть, которая отправляет запрос gRPC службе сервера.
@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
Аналогично службе генератора загрузки добавьте необходимые пакеты в pyproject.toml
с помощью следующей команды.
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation-flask=^0.20b0"
Затем попробуйте запустить приложение с помощью команды skaffold run
и посмотрите, что показывает панель управления Cloud Trace:
skaffold run --tail
После просмотра некоторых сообщений о сборке, отправке и развертывании вы увидите журналы приложений в форматах JSON. Перейдите в Cloud Trace > Список трассировки, чтобы проверить, получаете ли вы информацию о трассировке. Поскольку служба генератора нагрузки периодически отправляет запросы клиентской службе, а вы включили трассировку для всех запросов, вы начинаете видеть много точек в списке трассировки.
Нажав на один из них, вы увидите каскадный график, подобный приведенному ниже, который объясняет задержку каждой части процесса запроса и ответа. Установите флажок рядом с «Показать события», после чего вы получите аннотации внутри каскадного графика. Эти аннотации — это те, которые вы добавили в код с помощью метода span.add_event()
.
Вы можете заметить, что не видите промежутки из службы сервера. Это правильно, потому что мы вообще не интегрировали Span в серверную службу.
Краткое содержание
На этом этапе вы инструментировали службу генератора нагрузки и клиентскую службу и подтвердили, что можете успешно распространять контекст трассировки между службами и экспортировать информацию Span из обеих служб в Cloud Trace.
Дальше
На следующем этапе вы будете инструментировать клиентскую и серверную службы, чтобы подтвердить, как распространять контекст трассировки через gRPC.
5. Инструментарий для gRPC
На предыдущем шаге мы инструментировали первую половину запроса в этом микросервисе. На этом этапе мы пытаемся реализовать связь gRPC между службой клиента и службой сервера. (Зелено-фиолетовый прямоугольник на картинке ниже)
Автоматическое инструментирование для клиента gRPC
Экосистема OpenTelemetry предлагает множество удобных библиотек, которые помогают разработчикам инструментировать приложения. На предыдущем шаге мы использовали автоматическое инструментирование для модуля «запросы». На этом этапе, когда мы пытаемся распространить контекст трассировки через gRPC, мы используем для этого библиотеку.
источник/клиент/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()
Для обслуживания клиентов нам нужно сделать довольно мало инструментов. Мы хотим распространить контекст трассировки, который представляет собой комбинацию идентификатора трассировки и идентификатора диапазона текущего диапазона, через gRPC. Поэтому мы вызываем GrpcInstrumentatorClient.instrument()
, чтобы клиент gRPC в функции-обработчике мог встроить контекст трассировки в HTTP-заголовок ниже.
Обязательно добавьте новые зависимости в pyproject.toml
с помощью команды poetry add
:
poetry add "opentelemetry-instrumentation-grpc=^0.20b0"
Автоматическое оснащение сервера gRPC
Как и в случае с клиентом gRPC, мы вызываем автоматическое инструментирование для сервера gRPC. Добавьте импорт, как показано ниже, и вызовите GrpcInstrumentationServer().instrument()
в верхней части файла.
Внимание : обязательно позвоните.
GrpcInstrumentationServe()
на этом этапе не
GrpcInstrumentationClient()
.
источник/сервер/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()
+
Затем вы добавите экспортер для отправки информации трассировки в серверную часть Cloud Trace. Добавьте следующий код в функцию 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)
Обязательно добавьте новые пакеты в службу сервера.
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"
Запустите микросервис и подтвердите трассировку.
Затем запустите измененный код с помощью команды skaffold.
skaffold run --tail
Теперь вы снова видите кучу трассировок на странице списка трассировок Cloud Trace. Щелкните одну из трассировок, и теперь вы обнаружите, что она охватывает весь запрос от службы генератора нагрузки к службе сервера.
Краткое содержание
На этом этапе вы настроили связь на основе gRPC при поддержке библиотек экосистемы OpenTelemetry. Кроме того, вы подтвердили, что контекст трассировки, созданный в службе генератора нагрузки, был успешно доставлен в службу сервера.
6. Поздравления
Вы успешно создали распределенные трассировки с помощью OpenTelemery и подтвердили задержки запросов в микросервисе в Google Cloud Trace.
Для расширенных упражнений вы можете самостоятельно попробовать следующие темы.
- Текущая реализация отправляет все промежутки, созданные в результате проверки работоспособности. Как отфильтровать эти промежутки из Cloud Traces? Подсказка здесь .
- Сопоставьте журналы событий с интервалами и посмотрите, как это работает в Google Cloud Trace и Google Cloud Logging. Подсказка здесь .
- Замените какой-либо сервис сервисом на другом языке и попробуйте оснастить его OpenTelemetry для этого языка.
Внимание : Google Kubernetes Engine и Google Artifact Registry постоянно потребляют этот ресурс.
Очистить
После этой лабораторной работы остановите кластер Kubernetes и обязательно удалите проект, чтобы не получить неожиданные расходы на Google Kubernetes Engine, Google Cloud Trace, Google Artifact Registry.
Сначала удалите кластер с помощью следующей команды:
skaffold delete
Вывод команды
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
После удаления кластера в панели меню выберите «IAM и администратор» > «Настройки», а затем нажмите кнопку «ЗАВЕРШИТЬ».
Затем введите идентификатор проекта (а не имя проекта) в форму в диалоговом окне и подтвердите закрытие.