1. Введение
Последнее обновление: 15 июля 2022 г.
Наблюдаемость приложения
Наблюдаемость и OpenTelemetry
Наблюдаемость — это термин, используемый для описания атрибута системы. Система с возможностью наблюдения позволяет командам активно отлаживать свою систему. В этом контексте три столпа наблюдаемости; журналы, метрики и трассировки — это фундаментальные инструменты, позволяющие системе обеспечить наблюдаемость.
OpenTelemetry — это набор спецификаций, библиотек и агентов, которые ускоряют инструментирование и экспорт данных телеметрии (журналов, показателей и трассировок), необходимых для наблюдения. OpenTelemetry — это проект открытого стандарта, управляемый сообществом под эгидой CNCF. Используя библиотеки, предоставляемые проектом и его экосистемой, разработчики могут инструментировать свои приложения независимо от поставщика и с учетом различных архитектур.
Кроме того, в дополнение к трем столпам наблюдения, непрерывное профилирование является еще одним ключевым компонентом наблюдаемости и расширяет базу пользователей в отрасли. Cloud Profiler является одним из создателей и предоставляет простой интерфейс для детализации показателей производительности в стеках вызовов приложений.
Эта лаборатория кода является первой частью серии и охватывает инструментирование распределенных трассировок в микросервисах с помощью OpenTelemetry и Cloud Trace. Во второй части будет рассмотрено непрерывное профилирование с помощью Cloud Profiler.
Распределенная трассировка
Среди журналов, метрик и трассировок трассировка — это телеметрия, которая сообщает о задержке определенной части процесса в системе. Особенно в эпоху микросервисов распределенная трассировка является сильным стимулом для выявления узких мест задержки во всей распределенной системе.
При анализе распределенных трассировок визуализация данных трассировки является ключом к быстрому определению общих задержек системы. В распределенной трассировке мы обрабатываем набор вызовов для обработки одного запроса к точке входа в систему в форме трассировки, содержащей несколько промежутков.
Промежуток представляет собой отдельную единицу работы, выполняемую в распределенной системе, с записью времени начала и остановки. Промежутки часто имеют иерархические отношения между собой — на рисунке ниже все меньшие промежутки являются дочерними промежутками большого /messages и собраны в одну трассировку, которая показывает путь работы через систему.
Google Cloud Trace — это один из вариантов распределенной серверной части трассировки, который хорошо интегрируется с другими продуктами в Google Cloud.
Что ты построишь
В этой лаборатории кода вы собираетесь инструментировать информацию трассировки в сервисах под названием «Приложение Shakespeare» (также известное как Shakesapp), которые работают в кластере Google Kubernetes Engine. Архитектура Shakesapp описана ниже:
- Loadgen отправляет строку запроса клиенту по HTTP.
- Клиенты передают запрос от генератора нагрузки на сервер в gRPC.
- Сервер принимает запрос от клиента, извлекает все произведения Шекспира в текстовом формате из Google Cloud Storage, ищет строки, содержащие запрос, и возвращает номер строки, соответствующей клиенту.
Вы будете инструментировать информацию трассировки по всему запросу. После этого вы встроите агент профилировщика на сервер и исследуете узкое место.
Что вы узнаете
- Как начать работу с библиотеками OpenTelemetry Trace в проекте Go
- Как создать диапазон с помощью библиотеки
- Как передавать контексты диапазона по сети между компонентами приложения
- Как отправить данные трассировки в Cloud Trace
- Как проанализировать трассировку в Cloud Trace
В этой кодовой лаборатории объясняется, как инструментировать ваши микросервисы. Чтобы упростить понимание, этот пример содержит только 3 компонента (генератор нагрузки, клиент и сервер), но вы можете применить тот же процесс, описанный в этой кодовой лаборатории, к более сложным и большим системам.
Что вам понадобится
- Базовые знания Го
- Базовые знания Kubernetes
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 Artifact Registry указаны в официальной документации.
- Цены на операционный пакет Google Cloud | Операционный пакет
- Цены | Документация по движку 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
Вы можете выбрать множество различных зон. Дополнительную информацию см. в разделе «Регионы и зоны» .
Перейти к настройке языка
В этой лаборатории кода мы используем Go для всего исходного кода. Выполните следующую команду в Cloud Shell и убедитесь, что версия Go 1.17+.
go version
Вывод команды
go version go1.18.3 linux/amd64
Настройка кластера 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-codelab2 \ --zone us-central1-f \ --release-channel rapid \ --preemptible \ --enable-autoscaling \ --max-nodes 8 \ --no-enable-ip-alias \ --scopes cloud-platform
Вывод команды
Note: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s). Creating cluster otel-trace-codelab2 in us-central1-f... Cluster is being health-checked (master is healthy)...done. Created [https://container.googleapis.com/v1/projects/development-215403/zones/us-central1-f/clusters/otel-trace-codelab2]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-f/otel-trace-codelab2?project=development-215403 kubeconfig entry generated for otel-trace-codelab2. NAME: otel-trace-codelab2 LOCATION: us-central1-f MASTER_VERSION: 1.23.6-gke.1501 MASTER_IP: 104.154.76.89 MACHINE_TYPE: e2-medium NODE_VERSION: 1.23.6-gke.1501 NUM_NODES: 3 STATUS: 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.38.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 Registry для реестра контейнеров.
- Настройте skaffold для использования реестра контейнеров.
- Создан кластер Kubernetes, в котором работают микросервисы Codelab.
Дальше
На следующем этапе вы создадите, отправите и развернете свои микросервисы в кластере.
3. Создавайте, распространяйте и развертывайте микросервисы.
Загрузите материал codelab
На предыдущем шаге мы создали все необходимые условия для этой лаборатории кода. Теперь вы готовы запускать поверх них целые микросервисы. Материалы Codelab размещены на GitHub, поэтому загрузите их в среду Cloud Shell с помощью следующей команды git.
cd ~ git clone https://github.com/ymotongpoo/opentelemetry-trace-codelab-go.git cd opentelemetry-trace-codelab-go
Структура каталогов проекта следующая:
. ├── README.md ├── step0 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step1 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step2 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step3 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step4 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step5 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src └── step6 ├── manifests ├── proto ├── skaffold.yaml └── src
- манифесты: файлы манифеста Kubernetes.
- proto: определение протокола для связи между клиентом и сервером.
- src: каталоги с исходным кодом каждого сервиса.
- skaffold.yaml: файл конфигурации для skaffold.
В этой лаборатории кода вы обновите исходный код, расположенный в папке step0
. Вы также можете обратиться к исходному коду в папках step[1-6]
для получения ответов на следующих шагах. (Часть 1 охватывает шаги с 0 по 4, а часть 2 — шаги 5 и 6)
Запустить команду скаффолда
Наконец, вы готовы собирать, отправлять и развертывать весь контент в только что созданном кластере Kubernetes. Звучит так, как будто он содержит несколько шагов, но на самом деле skaffold делает все за вас. Давайте попробуем это с помощью следующей команды:
cd step0 skaffold dev
Как только вы запустите команду, вы увидите выходные данные журнала 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
После развертывания вы увидите фактические журналы приложений, отправляемые на стандартный вывод в каждом контейнере, например:
Вывод команды
[client] 2022/07/14 06:33:15 {"match_count":3040} [loadgen] 2022/07/14 06:33:15 query 'love': matched 3040 [client] 2022/07/14 06:33:15 {"match_count":3040} [loadgen] 2022/07/14 06:33:15 query 'love': matched 3040 [client] 2022/07/14 06:33:16 {"match_count":3040} [loadgen] 2022/07/14 06:33:16 query 'love': matched 3040 [client] 2022/07/14 06:33:19 {"match_count":463} [loadgen] 2022/07/14 06:33:19 query 'tear': matched 463 [loadgen] 2022/07/14 06:33:20 query 'world': matched 728 [client] 2022/07/14 06:33:20 {"match_count":728} [client] 2022/07/14 06:33:22 {"match_count":463} [loadgen] 2022/07/14 06:33:22 query 'tear': matched 463
Обратите внимание, что на этом этапе вы хотите видеть все сообщения с сервера. Хорошо, наконец, вы готовы приступить к оснащению своего приложения OpenTelemetry для распределенной трассировки служб.
Прежде чем приступить к оснащению службы, завершите работу кластера, нажав Ctrl-C.
Вывод команды
... [client] 2022/07/14 06:34:57 {"match_count":1} [loadgen] 2022/07/14 06:34:57 query 'what's past is prologue': matched 1 ^CCleaning up... - W0714 06:34:58.464305 28078 gcp.go:120] WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead. - To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
Краткое содержание
На этом этапе вы подготовили материал codelab в своей среде и подтвердили ожидаемое выполнение скаффолда.
Дальше
На следующем этапе вы измените исходный код службы loadgen для инструментирования информации трассировки.
4. Инструментарий для HTTP
Концепция инструментирования и распространения трассировки
Прежде чем редактировать исходный код, позвольте мне кратко объяснить, как работают распределенные трассировки, на простой диаграмме.
В этом примере мы используем код для экспорта информации Trace и Span в Cloud Trace и распространения контекста трассировки по запросу от службы Loadgen к серверной службе.
Приложениям необходимо отправлять метаданные трассировки, такие как идентификатор трассировки и идентификатор интервала, чтобы Cloud Trace мог объединить все интервалы с одинаковым идентификатором трассировки в одну трассировку. Кроме того, приложению необходимо распространять контексты трассировки (комбинацию идентификатора трассировки и идентификатора диапазона родительского диапазона) при запросе нижестоящих служб, чтобы они могли знать, какой контекст трассировки они обрабатывают.
OpenTelemetry поможет вам:
- для создания уникального идентификатора трассировки и идентификатора диапазона
- для экспорта идентификатора трассировки и идентификатора диапазона на серверную часть
- для распространения контекстов трассировки на другие службы
- встроить дополнительные метаданные, которые помогут анализировать следы
Компоненты в OpenTelemetry Trace
Процесс инструментирования трассировки приложения с помощью OpenTelemetry выглядит следующим образом:
- Создать экспортер
- Создайте TracerProvider, привязывающий экспортер в 1, и установите его глобальным.
- Установите TextMapPropagaror, чтобы установить метод распространения.
- Получите трассировщик от TracerProvider.
- Создать интервал из трассировщика
На данный момент вам не нужно разбираться в подробных свойствах каждого компонента, но самое важное, что следует запомнить:
- экспортер здесь можно подключить к TracerProvider
- TracerProvider хранит всю конфигурацию, касающуюся выборки и экспорта трассировки.
- все трассировки объединены в объект Tracer
Поняв это, давайте перейдем к собственно работе по кодированию.
Первый диапазон прибора
Сервис генератора инструментальной нагрузки
Откройте редактор Cloud Shell, нажав кнопку в правом верхнем углу Cloud Shell. Откройте step0/src/loadgen/main.go
из проводника на левой панели и найдите функцию main.
шаг0/src/loadgen/main.go
func main() { ... for range t.C { log.Printf("simulating client requests, round %d", i) if err := run(numWorkers, numConcurrency); err != nil { log.Printf("aborted round with error: %v", err) } log.Printf("simulated %d requests", numWorkers) if numRounds != 0 && i > numRounds { break } i++ } }
В основной функции вы видите цикл, вызывающий run
в нем функцию. В текущей реализации раздел имеет 2 строки журнала, в которых фиксируется начало и окончание вызова функции. Теперь давайте инструментируем информацию Span для отслеживания задержки вызова функции.
Сначала, как отмечалось в предыдущем разделе, давайте настроим все конфигурации для OpenTelemetry. Добавьте пакеты OpenTelemetry следующим образом:
шаг0/src/loadgen/main.go
import ( "context" // step1. add packages "encoding/json" "fmt" "io" "log" "math/rand" "net/http" "net/url" "time" // step1. add packages "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.10.0" "go.opentelemetry.io/otel/trace" // step1. end add packages )
Для удобства чтения мы создаем функцию настройки под названием initTracer
и вызываем ее в main
функции.
шаг0/src/loadgen/main.go
// step1. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // create a stdout exporter to show collected spans out to stdout. exporter, err := stdout.New(stdout.WithPrettyPrint()) if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil }
Вы можете заметить, что процедура настройки OpenTelemetry аналогична описанной в предыдущем разделе. В этой реализации мы используем экспортер stdout
, который экспортирует всю информацию трассировки в стандартный вывод в структурированном формате.
Затем вы вызываете его из основной функции. Вызовите initTracer()
и обязательно вызывайте TracerProvider.Shutdown()
при закрытии приложения.
шаг0/src/loadgen/main.go
func main() { // step1. setup OpenTelemetry tp, err := initTracer() if err != nil { log.Fatalf("failed to initialize TracerProvider: %v", err) } defer func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatalf("error shutting down TracerProvider: %v", err) } }() // step1. end setup log.Printf("starting worder with %d workers in %d concurrency", numWorkers, numConcurrency) log.Printf("number of rounds: %d (0 is inifinite)", numRounds) ...
После завершения настройки вам необходимо создать диапазон с уникальным идентификатором трассировки и идентификатором диапазона. OpenTelemetry предоставляет для этого удобную библиотеку. Добавьте дополнительные новые пакеты в HTTP-клиент прибора.
шаг0/src/loadgen/main.go
import ( "context" "encoding/json" "fmt" "io" "log" "math/rand" "net/http" "net/http/httptrace" // step1. add packages "net/url" "time" // step1. add packages "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" // step1. end add packages "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.10.0" "go.opentelemetry.io/otel/trace" )
Поскольку генератор нагрузки вызывает клиентскую службу по HTTP с помощью net/http
в функции runQuery
, мы используем пакет contrib для net/http
и включаем инструментирование с расширением httptrace
и пакета otelhttp
.
Сначала добавляем глобальную переменную пакета httpClient для вызова HTTP-запросов через инструментированный клиент.
шаг0/src/loadgen/main.go
var httpClient = http.Client{ Transport: otelhttp.NewTransport(http.DefaultTransport) }
Затем добавьте инструменты в функцию runQuery
для создания пользовательского диапазона с помощью OpenTelemetry и автоматически созданного диапазона из пользовательского HTTP-клиента. Что вы будете делать:
- Получите Tracer от глобального
TracerProvider
с помощьюotel.Tracer()
- Создайте корневой диапазон с помощью метода
Tracer.Start()
- Завершить корневой диапазон в произвольное время (в данном случае, конец функции
runQuery
).
шаг0/src/loadgen/main.go
reqURL.RawQuery = v.Encode() // step1. replace http.Get() with custom client call // resp, err := http.Get(reqURL.String()) // step1. instrument trace ctx := context.Background() tr := otel.Tracer("loadgen") ctx, span := tr.Start(ctx, "query.request", trace.WithAttributes( semconv.TelemetrySDKLanguageGo, semconv.ServiceNameKey.String("loadgen.runQuery"), attribute.Key("query").String(s), )) defer span.End() ctx = httptrace.WithClientTrace(ctx, otelhttptrace.NewClientTrace(ctx)) req, err := http.NewRequestWithContext(ctx, "GET", reqURL.String(), nil) if err != nil { return -1, fmt.Errorf("error creating HTTP request object: %v", err) } resp, err := httpClient.Do(req) // step1. end instrumentation if err != nil { return -1, fmt.Errorf("error sending request to %v: %v", reqURL.String(), err) }
Теперь вы закончили с инструментами в loadgen (клиентское приложение HTTP). Обязательно обновите файлы go.mod
и go.sum
с помощью команды go mod
.
go mod tidy
Клиентское обслуживание инструментов
В предыдущем разделе мы обработали деталь, обведенную красным прямоугольником на рисунке ниже. Мы инструментировали информацию о диапазоне в службе генератора нагрузки. Как и в случае со службой генератора нагрузки, теперь нам нужно инструментировать клиентскую службу. Отличие от службы генератора нагрузки заключается в том, что клиентской службе необходимо извлечь информацию Trace ID, передаваемую из службы генератора нагрузки, в заголовок HTTP, и использовать этот идентификатор для создания интервалов.
Откройте редактор Cloud Shell и добавьте необходимые пакеты, как мы это сделали для службы генератора нагрузки.
шаг0/src/клиент/main.go
import ( "context" "encoding/json" "fmt" "io" "log" "net/http" "net/url" "os" "time" "opentelemetry-trace-codelab-go/client/shakesapp" // step1. add new import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" // step1. end new import )
Опять же, нам нужно настроить OpenTelemtry. Просто скопируйте и вставьте функцию initTracer
из loadgen и вызовите ее также в main
функции клиентской службы.
шаг0/src/клиент/main.go
// step1. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // create a stdout exporter to show collected spans out to stdout. exporter, err := stdout.New(stdout.WithPrettyPrint()) if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil }
Теперь пришло время инструментальных пролетов. Поскольку клиентской службе необходимо принимать HTTP-запросы от службы генерации нагрузки, ей необходимо инструментировать обработчик. HTTP-сервер в клиентской службе реализован с помощью net/http, и вы можете использовать пакет otelhttp
, как мы делали в loadgen.
Сначала мы заменяем регистрацию обработчика на otelhttp
Handler. В main
функции найдите строки, в которых обработчик HTTP зарегистрирован с помощью http.HandleFunc()
.
шаг0/src/клиент/main.go
// step1. change handler to intercept OpenTelemetry related headers // http.HandleFunc("/", svc.handler) otelHandler := otelhttp.NewHandler(http.HandlerFunc(svc.handler), "client.handler") http.Handle("/", otelHandler) // step1. end intercepter setting http.HandleFunc("/_genki", svc.health)
Затем мы инструментируем фактический диапазон внутри обработчика. Найдите func (*clientService) handler() и добавьте инструментарий диапазона с помощью trace.SpanFromContext()
.
шаг0/src/клиент/main.go
func (cs *clientService) handler(w http.ResponseWriter, r *http.Request) { ... ctx := r.Context() ctx, cancel := context.WithCancel(ctx) defer cancel() // step1. instrument trace span := trace.SpanFromContext(ctx) defer span.End() // step1. end instrument ...
С помощью этого инструментария вы получаете промежутки от начала метода- handler
до его конца. Чтобы упростить анализ интервалов, добавьте в запрос дополнительный атрибут, который хранит количество совпадений. Прямо перед строкой журнала добавьте следующий код.
func (cs *clientService) handler(w http.ResponseWriter, r *http.Request) { ... // step1. add span specific attribute span.SetAttributes(attribute.Key("matched").Int64(resp.MatchCount)) // step1. end adding attribute log.Println(string(ret)) ...
Используя все вышеперечисленные инструменты, вы завершили инструментацию трассировки между loadgen и клиентом. Давайте посмотрим, как это работает. Запустите код с помощью skaffold еще раз.
skaffold dev
Через некоторое время после запуска служб в кластере GKE вы увидите огромное количество таких сообщений журнала:
Вывод команды
[loadgen] { [loadgen] "Name": "query.request", [loadgen] "SpanContext": { [loadgen] "TraceID": "cfa22247a542beeb55a3434392d46b89", [loadgen] "SpanID": "18b06404b10c418b", [loadgen] "TraceFlags": "01", [loadgen] "TraceState": "", [loadgen] "Remote": false [loadgen] }, [loadgen] "Parent": { [loadgen] "TraceID": "00000000000000000000000000000000", [loadgen] "SpanID": "0000000000000000", [loadgen] "TraceFlags": "00", [loadgen] "TraceState": "", [loadgen] "Remote": false [loadgen] }, [loadgen] "SpanKind": 1, [loadgen] "StartTime": "2022-07-14T13:13:36.686751087Z", [loadgen] "EndTime": "2022-07-14T13:14:31.849601964Z", [loadgen] "Attributes": [ [loadgen] { [loadgen] "Key": "telemetry.sdk.language", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "go" [loadgen] } [loadgen] }, [loadgen] { [loadgen] "Key": "service.name", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "loadgen.runQuery" [loadgen] } [loadgen] }, [loadgen] { [loadgen] "Key": "query", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "faith" [loadgen] } [loadgen] } [loadgen] ], [loadgen] "Events": null, [loadgen] "Links": null, [loadgen] "Status": { [loadgen] "Code": "Unset", [loadgen] "Description": "" [loadgen] }, [loadgen] "DroppedAttributes": 0, [loadgen] "DroppedEvents": 0, [loadgen] "DroppedLinks": 0, [loadgen] "ChildSpanCount": 5, [loadgen] "Resource": [ [loadgen] { [loadgen] "Key": "service.name", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "unknown_service:loadgen" ...
Экспортер stdout
выдает эти сообщения. Вы заметите, что родительские элементы всех промежутков по loadgen имеют TraceID: 00000000000000000000000000000000
, поскольку это корневой промежуток, т.е. первый промежуток в трассировке. Также вы обнаружите, что атрибут внедрения "query"
содержит строку запроса, которая передается в клиентскую службу.
Краткое содержание
На этом этапе вы инструментировали службу генератора нагрузки и клиентскую службу, которые обмениваются данными по HTTP, и подтвердили, что можете успешно распространять контекст трассировки между службами и экспортировать информацию Span из обеих служб в стандартный вывод.
Дальше
На следующем этапе вы будете инструментировать клиентскую и серверную службы, чтобы подтвердить, как распространять контекст трассировки через gRPC.
5. Инструментарий для gRPC
На предыдущем шаге мы инструментировали первую половину запроса в этом микросервисе. На этом этапе мы пытаемся реализовать связь gRPC между службой клиента и службой сервера. (Зелено-фиолетовый прямоугольник на картинке ниже)
Предварительная сборка инструментов для клиента gRPC
Экосистема OpenTelemetry предлагает множество удобных библиотек, которые помогают разработчикам инструментировать приложения. На предыдущем шаге мы использовали инструменты предварительной сборки для пакета net/http
. На этом этапе, когда мы пытаемся распространить контекст трассировки через gRPC, мы используем для этого библиотеку.
Сначала вы импортируете готовый пакет gRPC под названием otelgrpc
.
шаг0/src/клиент/main.go
import ( "context" "encoding/json" "fmt" "io" "log" "net/http" "net/url" "os" "time" "opentelemetry-trace-codelab-go/client/shakesapp" // step2. add prebuilt gRPC package (otelgrpc) "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" )
На этот раз клиентская служба представляет собой клиент gRPC по отношению к службе сервера, поэтому вам необходимо инструментировать клиент gRPC. Найдите функцию mustConnGRPC
и добавьте перехватчики gRPC, которые обрабатывают новые промежутки каждый раз, когда клиент отправляет запросы серверу.
шаг0/src/клиент/main.go
// Helper function for gRPC connections: Dial and create client once, reuse. func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr string) { var err error // step2. add gRPC interceptor interceptorOpt := otelgrpc.WithTracerProvider(otel.GetTracerProvider()) *conn, err = grpc.DialContext(ctx, addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor(interceptorOpt)), grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor(interceptorOpt)), grpc.WithTimeout(time.Second*3), ) // step2: end adding interceptor if err != nil { panic(fmt.Sprintf("Error %s grpc: failed to connect %s", err, addr)) } }
Поскольку вы уже настроили OpenTelemetry в предыдущем разделе, вам не нужно этого делать.
Готовые инструменты для сервера gRPC.
Как и в случае с клиентом gRPC, мы вызываем готовые инструменты для сервера gRPC. Добавьте новый пакет в раздел импорта, например:
шаг0/src/сервер/main.go
import ( "context" "fmt" "io/ioutil" "log" "net" "os" "regexp" "strings" "opentelemetry-trace-codelab-go/server/shakesapp" "cloud.google.com/go/storage" // step2. add OpenTelemetry packages including otelgrpc "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/otel" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/grpc" healthpb "google.golang.org/grpc/health/grpc_health_v1" )
Поскольку это первый раз, когда вы инструментируете сервер, вам необходимо сначала настроить OpenTelemetry, аналогично тому, что мы делали для нагрузки и клиентских служб.
шаг0/src/сервер/main.go
// step2. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // create a stdout exporter to show collected spans out to stdout. exporter, err := stdout.New(stdout.WithPrettyPrint()) if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil } func main() { ... // step2. setup OpenTelemetry tp, err := initTracer() if err != nil { log.Fatalf("failed to initialize TracerProvider: %v", err) } defer func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatalf("error shutting down TracerProvider: %v", err) } }() // step2. end setup ...
Далее вам нужно добавить серверные перехватчики. В main
функции найдите место вызова grpc.NewServer()
и добавьте в функцию перехватчики.
шаг0/src/сервер/main.go
func main() { ... svc := NewServerService() // step2: add interceptor interceptorOpt := otelgrpc.WithTracerProvider(otel.GetTracerProvider()) srv := grpc.NewServer( grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor(interceptorOpt)), grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor(interceptorOpt)), ) // step2: end adding interceptor shakesapp.RegisterShakespeareServiceServer(srv, svc) ...
Запустите микросервис и подтвердите трассировку.
Затем запустите измененный код с помощью команды skaffold.
skaffold dev
Теперь вы снова видите кучу информации о диапазонах на стандартном выводе.
Вывод команды
... [server] { [server] "Name": "shakesapp.ShakespeareService/GetMatchCount", [server] "SpanContext": { [server] "TraceID": "89b472f213a400cf975e0a0041649667", [server] "SpanID": "96030dbad0061b3f", [server] "TraceFlags": "01", [server] "TraceState": "", [server] "Remote": false [server] }, [server] "Parent": { [server] "TraceID": "89b472f213a400cf975e0a0041649667", [server] "SpanID": "cd90cc3859b73890", [server] "TraceFlags": "01", [server] "TraceState": "", [server] "Remote": true [server] }, [server] "SpanKind": 2, [server] "StartTime": "2022-07-14T14:05:55.74822525Z", [server] "EndTime": "2022-07-14T14:06:03.449258891Z", [server] "Attributes": [ ... [server] ], [server] "Events": [ [server] { [server] "Name": "message", [server] "Attributes": [ ... [server] ], [server] "DroppedAttributeCount": 0, [server] "Time": "2022-07-14T14:05:55.748235489Z" [server] }, [server] { [server] "Name": "message", [server] "Attributes": [ ... [server] ], [server] "DroppedAttributeCount": 0, [server] "Time": "2022-07-14T14:06:03.449255889Z" [server] } [server] ], [server] "Links": null, [server] "Status": { [server] "Code": "Unset", [server] "Description": "" [server] }, [server] "DroppedAttributes": 0, [server] "DroppedEvents": 0, [server] "DroppedLinks": 0, [server] "ChildSpanCount": 0, [server] "Resource": [ [server] { ... [server] ], [server] "InstrumentationLibrary": { [server] "Name": "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc", [server] "Version": "semver:0.33.0", [server] "SchemaURL": "" [server] } [server] } ...
Вы заметили, что не встроили имена диапазонов и не создали диапазоны вручную с помощью trace.Start()
или span.SpanFromContext()
. Тем не менее вы получаете большое количество промежутков, поскольку их генерируют перехватчики gRPC.
Краткое содержание
На этом этапе вы настроили связь на основе gRPC при поддержке библиотек экосистемы OpenTelemetry.
Дальше
На следующем этапе вы, наконец, визуализируете трассировку с помощью Cloud Trace и научитесь анализировать собранные интервалы.
6. Визуализация трассировки с помощью Cloud Trace
Вы инструментировали трассировку во всей системе с помощью OpenTelemetry. На данный момент вы узнали, как инструментировать службы HTTP и gRPC. Хотя вы и научились их инструментировать, вы еще не научились их анализировать. В этом разделе вы замените экспортеры stdout экспортерами Cloud Trace и узнаете, как анализировать трассировки.
Использовать экспортер Cloud Trace
Одной из мощных характеристик OpenTelemetry является возможность подключения. Чтобы визуализировать все интервалы, собранные вашими инструментами, вам нужно просто заменить экспортер stdout экспортером Cloud Trace.
Откройте файлы main.go
каждого сервиса и найдите функцию initTracer()
. Удалите строку, чтобы создать экспортер стандартного вывода, и вместо этого создайте экспортер Cloud Trace.
шаг0/src/loadgen/main.go
import ( ... // step3. add OpenTelemetry for Cloud Trace package cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace" ) // step1. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // step3. replace stdout exporter with Cloud Trace exporter // cloudtrace.New() finds the credentials to Cloud Trace automatically following the // rules defined by golang.org/x/oauth2/google.findDefaultCredentailsWithParams. // https://pkg.go.dev/golang.org/x/oauth2/google#FindDefaultCredentialsWithParams exporter, err := cloudtrace.New() // step3. end replacing exporter if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil }
Вам также необходимо отредактировать одну и ту же функцию в службе клиента и сервера.
Запустите микросервис и подтвердите трассировку.
После редактирования просто запустите кластер как обычно с помощью команды skaffold.
skaffold dev
Теперь вы не видите много информации о интервале в формате структурированных журналов на стандартном выводе, потому что вы заменили экспортер на Cloud Trace.
Вывод команды
[loadgen] 2022/07/14 15:01:07 simulated 20 requests [loadgen] 2022/07/14 15:01:07 simulating client requests, round 37 [loadgen] 2022/07/14 15:01:14 query 'sweet': matched 958 [client] 2022/07/14 15:01:14 {"match_count":958} [client] 2022/07/14 15:01:14 {"match_count":3040} [loadgen] 2022/07/14 15:01:14 query 'love': matched 3040 [client] 2022/07/14 15:01:15 {"match_count":349} [loadgen] 2022/07/14 15:01:15 query 'hello': matched 349 [client] 2022/07/14 15:01:15 {"match_count":484} [loadgen] 2022/07/14 15:01:15 query 'faith': matched 484 [loadgen] 2022/07/14 15:01:15 query 'insolence': matched 14 [client] 2022/07/14 15:01:15 {"match_count":14} [client] 2022/07/14 15:01:21 {"match_count":484} [loadgen] 2022/07/14 15:01:21 query 'faith': matched 484 [client] 2022/07/14 15:01:21 {"match_count":728} [loadgen] 2022/07/14 15:01:21 query 'world': matched 728 [client] 2022/07/14 15:01:22 {"match_count":484} [loadgen] 2022/07/14 15:01:22 query 'faith': matched 484 [loadgen] 2022/07/14 15:01:22 query 'hello': matched 349 [client] 2022/07/14 15:01:22 {"match_count":349} [client] 2022/07/14 15:01:23 {"match_count":1036} [loadgen] 2022/07/14 15:01:23 query 'friend': matched 1036 [loadgen] 2022/07/14 15:01:28 query 'tear': matched 463 ...
Теперь давайте проверим, правильно ли отправлены все промежутки в Cloud Trace. Откройте консоль Cloud и перейдите к «Списку трассировки». Доступ к нему легко получить из окна поиска. В противном случае вы можете щелкнуть меню на левой панели.
Затем вы видите множество синих пятен, распределенных по графику задержки. Каждое пятно представляет собой отдельный след.
Щелкните один из них, и вы увидите детали внутри трассировки.
Даже из этого простого беглого взгляда вы уже знаете много идей. Например, из каскадного графика видно, что причина задержки в основном связана с диапазоном с именем shakesapp.ShakespeareService/GetMatchCount
. (См. цифру 1 на изображении выше). Вы можете подтвердить это из сводной таблицы. (Самый правый столбец показывает продолжительность каждого промежутка.) Также эта трассировка была для запроса «друг». (См. 2 на изображении выше)
Проведя этот краткий анализ, вы можете понять, что вам нужно знать более детальные диапазоны внутри метода GetMatchCount
. По сравнению со стандартной информацией визуализация является мощным инструментом. Чтобы узнать больше о деталях Cloud Trace, посетите нашу официальную документацию .
Краткое содержание
На этом этапе вы заменили экспортер стандартного вывода на Cloud Trace и визуализировали трассировки в Cloud Trace. Также вы узнали, как начать анализировать следы.
Дальше
На следующем шаге вы измените исходный код серверной службы, добавив дополнительный диапазон в GetMatchCount.
7. Добавьте дополнительный диапазон для лучшего анализа.
На предыдущем шаге вы обнаружили, что причиной времени туда и обратно, наблюдаемого из loadgen, в основном является процесс внутри метода GetMatchCount, обработчика gRPC, в серверной службе. Однако, поскольку мы не реализовали ничего, кроме обработчика, мы не можем получить дополнительную информацию из каскадного графа. Это обычный случай, когда мы начинаем инструментировать микросервисы.
В этом разделе мы собираемся инструментировать поддиапазон, в котором сервер вызывает Google Cloud Storage, поскольку обычно процесс ввода-вывода из внешней сети занимает много времени, и важно определить, является ли вызов причиной.
Инструментирование поддиапазона на сервере
Откройте main.go
на сервере и найдите функцию readFiles
. Эта функция вызывает запрос в Google Cloud Storage на получение всех текстовых файлов произведений Шекспира. В этой функции вы можете создать поддиапазон, подобно тому, как вы это делали для инструментов HTTP-сервера в клиентской службе.
шаг0/src/сервер/main.go
func readFiles(ctx context.Context, bucketName, prefix string) ([]string, error) { type resp struct { s string err error } // step4: add an extra span span := trace.SpanFromContext(ctx) span.SetName("server.readFiles") span.SetAttributes(attribute.Key("bucketname").String(bucketName)) defer span.End() // step4: end add span ...
И это все для добавления нового пролета. Давайте посмотрим, как это происходит, запустив приложение.
Запустите микросервис и подтвердите трассировку.
После редактирования просто запустите кластер как обычно с помощью команды skaffold.
skaffold dev
И выберите одну трассировку с именем query.request
из списка трассировок. Вы увидите аналогичный каскадный график трассировки, за исключением нового диапазона в shakesapp.ShakespeareService/GetMatchCount
. (Диапазон, заключенный в красный прямоугольник ниже)
Из этого графика вы можете сказать, что внешний вызов Google Cloud Storage занимает большую задержку, но большую часть задержки составляют другие процессы.
Вы уже получили много информации, просто просмотрев каскадный график трассировки. Как получить дополнительную информацию о производительности в вашем приложении? Здесь на помощь приходит профилировщик, но на этом давайте завершим эту лабораторную работу и перенесем все руководства по профилировщику во вторую часть.
Краткое содержание
На этом этапе вы внедрили еще один диапазон в серверной службе и получили дополнительную информацию о задержке системы.
8. Поздравления
Вы успешно создали распределенные трассировки с помощью OpenTelemery и подтвердили задержки запросов в микросервисе в Google Cloud Trace.
Для расширенных упражнений вы можете самостоятельно попробовать следующие темы.
- Текущая реализация отправляет все промежутки, созданные в результате проверки работоспособности. (
grpc.health.v1.Health/Check
) Как отфильтровать эти промежутки из Cloud Traces? Подсказка здесь . - Сопоставьте журналы событий с интервалами и посмотрите, как это работает в Google Cloud Trace и Google Cloud Logging. Подсказка здесь .
- Замените какой-либо сервис сервисом на другом языке и попытайтесь оснастить его OpenTelemetry для этого языка.
Кроме того, если после этого вы захотите узнать о профилировщике, перейдите к части 2. В этом случае вы можете пропустить раздел очистки ниже.
Очистить
После этой лабораторной работы остановите кластер Kubernetes и обязательно удалите проект, чтобы не получить неожиданные расходы на Google Kubernetes Engine, Google Cloud Trace, Google Artifact Registry.
Сначала удалите кластер. Если вы запускаете кластер с помощью skaffold dev
, вам просто нужно нажать Ctrl-C. Если вы запускаете кластер с помощью skaffold run
, выполните следующую команду:
skaffold delete
Вывод команды
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
После удаления кластера в панели меню выберите «IAM и администратор» > «Настройки», а затем нажмите кнопку «ЗАВЕРШИТЬ».
Затем введите идентификатор проекта (а не имя проекта) в форму в диалоговом окне и подтвердите закрытие.