1. Введение
В этой лабораторной работе вы будете использовать gRPC для создания клиента и сервера, которые составят основу приложения сопоставления маршрутов, написанного на C++.
К концу руководства у вас будет простое приложение gRPC HelloWorld, оснащенное плагином gRPC OpenTelemetry, и вы сможете просматривать экспортированные показатели наблюдаемости в Prometheus.
Чему вы научитесь
- Как настроить плагин OpenTelemetry для существующего приложения gRPC C++
- Запуск локального экземпляра Prometheus
- Экспорт метрик в Prometheus
- Просмотр показателей на панели инструментов Prometheus
2. Прежде чем начать
Что вам понадобится
-
git -
curl -
build-essential -
clang -
bazelдля создания примеров в этой кодовой лаборатории
Установите необходимые компоненты:
sudo apt-get update -y
sudo apt-get upgrade -y
sudo apt-get install -y git curl build-essential clang
bazel можно установить через bazelisk . Последнюю версию можно найти здесь .
Самый простой способ настройки — установить его как двоичный файл bazel в вашем PATH следующим образом:
sudo cp bazelisk-linux-amd64 /usr/local/bin/bazel
sudo chmod a+x /usr/local/bin/bazel
В качестве альтернативы вы также можете использовать CMake. Инструкции по использованию CMake можно найти здесь .
Получить код
Для упрощения обучения эта практическая работа предлагает готовый исходный код, который поможет вам начать работу. Следующие шаги помогут вам настроить плагин gRPC OpenTelemetry в приложении.
grpc-codelabs
Исходный код scaffold для этой лабораторной работы доступен в этом каталоге GitHub. Если вы предпочитаете не реализовывать код самостоятельно, готовый исходный код доступен в каталоге Completed .
Сначала клонируйте репозиторий grpc codelab и перейдите в папку grpc-cpp-opentelemetry:
git clone https://github.com/grpc-ecosystem/grpc-codelabs.git
cd grpc-codelabs/codelabs/grpc-cpp-opentelemetry/
Кроме того, вы можете загрузить .zip-файл, содержащий только каталог codelab, и вручную распаковать его.
Создайте библиотеку gRPC с помощью bazel:
bazel build start_here/...
3. Зарегистрируйте плагин OpenTelemetry.
Для добавления плагина gRPC OpenTelemetry нам понадобится приложение gRPC. В этой лабораторной работе мы будем использовать простой клиент и сервер gRPC HelloWorld, которые будем оснащать плагином gRPC OpenTelemetry.
Первый шаг — зарегистрировать плагин OpenTelemetry, настроенный с помощью экспортера Prometheus в клиенте. Откройте codelabs/grpc-cpp-opentelemetry/start_here/greeter_callback_client.cc в вашем любимом редакторе и преобразуйте main() следующим образом:
int main(int argc, char **argv) {
absl::ParseCommandLine(argc, argv);
// Codelab Solution: Register a global gRPC OpenTelemetry plugin configured
// with a prometheus exporter.
opentelemetry::exporter::metrics::PrometheusExporterOptions opts;
opts.url = absl::GetFlag(FLAGS_prometheus_endpoint);
auto prometheus_exporter =
opentelemetry::exporter::metrics::PrometheusExporterFactory::Create(opts);
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
// The default histogram boundaries are not granular enough for RPCs. Override
// the "grpc.client.attempt.duration" view as recommended by
// https://github.com/grpc/proposal/blob/master/A66-otel-stats.md.
AddLatencyView(meter_provider.get(), "grpc.client.attempt.duration", "s");
meter_provider->AddMetricReader(std::move(prometheus_exporter));
auto status = grpc::OpenTelemetryPluginBuilder()
.SetMeterProvider(std::move(meter_provider))
.BuildAndRegisterGlobal();
if (!status.ok()) {
std::cerr << "Failed to register gRPC OpenTelemetry Plugin: "
<< status.ToString() << std::endl;
return static_cast<int>(status.code());
}
// Continuously send RPCs.
RunClient(absl::GetFlag(FLAGS_target));
return 0;
}
Следующий шаг — добавить плагин OpenTelemetry на сервер. Откройте codelabs/grpc-cpp-opentelemetry/start_here/greeter_callback_server.cc и преобразуйте main следующим образом:
int main(int argc, char** argv) {
absl::ParseCommandLine(argc, argv);
// Register a global gRPC OpenTelemetry plugin configured with a prometheus
// exporter.
opentelemetry::exporter::metrics::PrometheusExporterOptions opts;
opts.url = absl::GetFlag(FLAGS_prometheus_endpoint);
auto prometheus_exporter =
opentelemetry::exporter::metrics::PrometheusExporterFactory::Create(opts);
auto meter_provider =
std::make_shared<opentelemetry::sdk::metrics::MeterProvider>();
// The default histogram boundaries are not granular enough for RPCs. Override
// the "grpc.server.call.duration" view as recommended by
// https://github.com/grpc/proposal/blob/master/A66-otel-stats.md.
AddLatencyView(meter_provider.get(), "grpc.server.call.duration", "s");
meter_provider->AddMetricReader(std::move(prometheus_exporter));
auto status = grpc::OpenTelemetryPluginBuilder()
.SetMeterProvider(std::move(meter_provider))
.BuildAndRegisterGlobal();
if (!status.ok()) {
std::cerr << "Failed to register gRPC OpenTelemetry Plugin: "
<< status.ToString() << std::endl;
return static_cast<int>(status.code());
}
RunServer(absl::GetFlag(FLAGS_port));
return 0;
}
Для удобства необходимые заголовочные файлы и зависимости сборки уже добавлены.
#include "opentelemetry/exporters/prometheus/exporter_factory.h"
#include "opentelemetry/exporters/prometheus/exporter_options.h"
#include "opentelemetry/sdk/metrics/meter_provider.h"
#include <grpcpp/ext/otel_plugin.h>
Зависимости сборки также уже добавлены в файл BUILD -
cc_binary(
name = "greeter_callback_client",
srcs = ["greeter_callback_client.cc"],
defines = ["BAZEL_BUILD"],
deps = [
"//util:util",
"@com_github_grpc_grpc//:grpc++",
"@com_github_grpc_grpc//:grpcpp_otel_plugin",
"@com_google_absl//absl/flags:flag",
"@com_google_absl//absl/flags:parse",
"@io_opentelemetry_cpp//exporters/prometheus:prometheus_exporter",
"@io_opentelemetry_cpp//sdk/src/metrics",
],
)
4. Запуск примера и просмотр показателей
Чтобы запустить сервер, выполните -
bazel run start_here:greeter_callback_server
При успешной настройке вы увидите следующий вывод для сервера:
Server listening on 0.0.0.0:50051
Пока сервер работает, на другом терминале запустите клиент -
bazel run start_here:greeter_callback_client
Успешный запуск будет выглядеть так:
Greeter received: Hello world
Greeter received: Hello world
Greeter received: Hello world
Greeter received: Hello world
Greeter received: Hello world
Greeter received: Hello world
Greeter received: Hello world
Greeter received: Hello world
Greeter received: Hello world
Greeter received: Hello world
Greeter received: Hello world
Поскольку мы настроили плагин gRPC OpenTelemetry для экспорта метрик через Prometheus, эти метрики будут доступны по адресу localhost:9464 для сервера и localhost:9465 для клиента.
Чтобы увидеть показатели клиента -
curl localhost:9465/metrics
Результат будет иметь вид -
# HELP exposer_transferred_bytes_total Transferred bytes to metrics services
# TYPE exposer_transferred_bytes_total counter
exposer_transferred_bytes_total 0
# HELP exposer_scrapes_total Number of times metrics were scraped
# TYPE exposer_scrapes_total counter
exposer_scrapes_total 0
# HELP exposer_request_latencies Latencies of serving scrape requests, in microseconds
# TYPE exposer_request_latencies summary
exposer_request_latencies_count 0
exposer_request_latencies_sum 0
exposer_request_latencies{quantile="0.5"} Nan
exposer_request_latencies{quantile="0.9"} Nan
exposer_request_latencies{quantile="0.99"} Nan
# HELP target Target metadata
# TYPE target gauge
target_info{otel_scope_name="grpc-c++",otel_scope_version="1.67.0-dev",service_name="unknown_service",telemetry_sdk_version="1.13.0",telemetry_sdk_name="opentelemetry",telemetry_sdk_language="cpp"} 1 1721958543107
# HELP grpc_client_attempt_rcvd_total_compressed_message_size_bytes Compressed message bytes received per call attempt
# TYPE grpc_client_attempt_rcvd_total_compressed_message_size_bytes histogram
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_count{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-c++",otel_scope_version="1.67.0-dev"} 96 1721958543107
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_sum{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-c++",otel_scope_version="1.67.0-dev"} 1248 1721958543107
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-c++",otel_scope_version="1.67.0-dev",le="0"} 0 1721958543107
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-c++",otel_scope_version="1.67.0-dev",le="5"} 0 1721958543107
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-c++",otel_scope_version="1.67.0-dev",le="10"} 0 1721958543107
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-c++",otel_scope_version="1.67.0-dev",le="25"} 96 1721958543107
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-c++",otel_scope_version="1.67.0-dev",le="50"} 96 1721958543107
grpc_client_attempt_rcvd_total_compressed_message_size_bytes_bucket{grpc_method="helloworld.Greeter/SayHello",grpc_status="OK",grpc_target="dns:///localhost:50051",otel_scope_name="grpc-c++",otel_scope_version="1.67.0-dev",le="75"} 96 1721958543107
Аналогично для показателей на стороне сервера -
curl localhost:9464/metrics
5. Просмотр метрик на Prometheus
Здесь мы настроим экземпляр Prometheus, который будет собирать данные с нашего клиента и сервера gRPC, которые экспортируют метрики с помощью Prometheus.
Загрузите последнюю версию Prometheus для вашей платформы, затем извлеките и запустите ее:
tar xvfz prometheus-*.tar.gz
cd prometheus-*
Создайте файл конфигурации Prometheus со следующим содержимым:
cat > grpc_otel_cpp_prometheus.yml <<EOF
scrape_configs:
- job_name: "prometheus"
scrape_interval: 5s
static_configs:
- targets: ["localhost:9090"]
- job_name: "grpc-otel-cpp"
scrape_interval: 5s
static_configs:
- targets: ["localhost:9464", "localhost:9465"]
EOF
Запустите Prometheus с новой конфигурацией -
./prometheus --config.file=grpc_otel_cpp_prometheus.yml
Это позволит настроить считывание показателей из клиентских и серверных процессов кодовой лаборатории каждые 5 секунд.
Чтобы просмотреть метрики, перейдите по адресу http://localhost:9090/graph . Например, запрос:
histogram_quantile(0.5, rate(grpc_client_attempt_duration_seconds_bucket[1m]))
покажет график со средней задержкой попытки, используя 1 минуту в качестве временного окна для расчета квантиля.
Скорость запросов -
increase(grpc_client_attempt_duration_seconds_bucket[1m])
6. (Необязательно) Упражнение для пользователя
На панелях мониторинга Prometheus вы заметите низкий показатель QPS. Попробуйте найти в примере какой-нибудь подозрительный код, который ограничивает QPS.
Для энтузиастов: клиентский код ограничивается только одним ожидающим RPC-запросом в любой момент времени. Это можно изменить, чтобы клиент отправлял больше RPC-запросов, не дожидаясь завершения предыдущих. (Решение этой проблемы пока не предоставлено.)