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 هذا. إذا كنت تفضّل عدم تنفيذ الرمز بنفسك، يتوفّر الرمز المصدر المكتمل في الدليل completed.
أولاً، استنسِخ مستودع grpc codelab وانتقِل إلى المجلد grpc-cpp-opentelemetry:
git clone 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
سيؤدي ذلك إلى ضبط مقاييس من عمليات codelab الخاصة بالعميل والخادم ليتم جمعها كل 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، ستلاحظ أنّ عدد الطلبات في الثانية منخفض. تحقَّق ممّا إذا كان بإمكانك تحديد بعض الرموز المشبوهة في المثال التي تحدّ من عدد الطلبات في الثانية.
بالنسبة إلى المستخدمين المتحمّسين، يقتصر رمز العميل على طلب إجراء مكالمة إجراء عن بُعد واحدة فقط في لحظة معيّنة. يمكن تعديل ذلك ليتمكّن العميل من إرسال المزيد من طلبات RPC بدون انتظار اكتمال الطلبات السابقة. (لم يتم تقديم حلّ لهذه المشكلة).