1- مقدمة
في هذا الدرس التطبيقي حول الترميز، ستستخدم gRPC لإنشاء عميل وخادم يشكّلان الأساس لتطبيق يحدّد المسارات مكتوب بلغة C++.
في نهاية البرنامج التعليمي، سيكون لديك تطبيق gRPC HelloWorld بسيط مزوّد بالمكوّن الإضافي gRPC OpenTelemetry وستتمكّن من الاطّلاع على مقاييس إمكانية تتبّع البيانات التي تم تصديرها في Prometheus.
أهداف الدورة التعليمية
- كيفية إعداد المكوّن الإضافي OpenTelemetry لتطبيق gRPC C++ حالي
- تشغيل نسخة Prometheus محلية
- تصدير المقاييس إلى Prometheus
- عرض المقاييس من لوحة بيانات Prometheus
2. قبل البدء
المتطلبات
gitcurlbuild-essentialclangbazelلإنشاء الأمثلة في هذا الدرس التطبيقي حول الترميز
ثبِّت المتطلبات الأساسية:
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
يتوفّر رمز المصدر للبنية الأساسية لهذا الدرس التطبيقي حول الترميز في دليل github هذا directory. إذا كنت تفضّل عدم تنفيذ الرمز بنفسك، يتوفّر رمز المصدر المكتمل في دليل completed.
أولاً، استنسِخ مستودع grpc codelab وانتقِل إلى مجلد grpc-cpp-opentelemetry:
git clone -b v1 https://github.com/grpc-ecosystem/grpc-codelabs.git
cd grpc-codelabs/codelabs/grpc-cpp-opentelemetry/
بدلاً من ذلك، يمكنك تنزيل ملف .zip الذي يحتوي على دليل الدرس التطبيقي حول الترميز فقط وفك ضغطه يدويًا.
أنشئ مكتبة gRPC باستخدام bazel:
bazel build start_here/...
3. تسجيل المكوّن الإضافي OpenTelemetry
نحتاج إلى تطبيق gRPC لإضافة المكوّن الإضافي gRPC OpenTelemetry. في هذا الدرس التطبيقي حول الترميز، سنستخدم عميل وخادم 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]))
سيُظهر رسمًا بيانيًا بمتوسط وقت استجابة المحاولة باستخدام دقيقة واحدة كإطار زمني لحساب الكمية.
معدّل طلبات البحث -
increase(grpc_client_attempt_duration_seconds_bucket[1m])
6. (اختياري) تمرين للمستخدم
في لوحات بيانات prometheus، ستلاحظ أنّ طلبات البحث في الثانية منخفضة. حاول تحديد بعض الرموز المشبوهة في المثال التي تحدّ من طلبات البحث في الثانية.
بالنسبة إلى المستخدمين المتحمّسين، يقتصر رمز العميل على طلب إجراء واحد معلّق في لحظة معيّنة. يمكن تعديل ذلك بحيث يرسل العميل المزيد من طلبات إجراءات بدون انتظار اكتمال الطلبات السابقة. (لم يتم تقديم الحلّ لذلك.)