1. مقدمة
تاريخ آخر تعديل: 15/07/2022
إمكانية تتبّع التطبيق
قابلية الرصد وقياس OpenTelemetry
الملاحظة هي المصطلح المستخدم لوصف سمة أي نظام. يسمح النظام مع إمكانية الملاحظة للفرق بتصحيح أخطاء نظامهم بشكل نشط. وفي هذا السياق، توجد ثلاث ركائز للملاحظة؛ والسجلات والمقاييس والتتبعات هي الأدوات الأساسية التي يستخدمها النظام لاكتساب إمكانية الملاحظة.
خدمة OpenTelemetry هي مجموعة من المواصفات والمكتبات والبرامج الوكيلة التي تعمل على تسريع عملية قياس حالة بيانات القياس عن بُعد وتصديرها (السجلّات والمقاييس والتتبّعات) التي تتطلّبها ميزة الملاحظة. OpenTelemetry هو مشروع بمعيار مفتوح يرتكز على المجتمع وبرنامج CNCF. من خلال استخدام المكتبات التي يوفرها المشروع ومنظومته المتكاملة، يستطيع المطوّرون قياس استخدامات تطبيقاتهم بطريقة محايدة من جانب البائع ومقابل بنيات متعددة.
بالإضافة إلى الركائز الثلاث للملاحظة، يُعدّ التحليل المستمر عنصرًا رئيسيًا آخر في إمكانية الملاحظة وتوسيع قاعدة المستخدمين في المجال. أداة Cloud Profiler هي إحدى أدوات الإنشاء وتوفّر واجهة سهلة للتوغّل في مقاييس الأداء في حِزم طلبات التطبيقات.
هذا الدرس التطبيقي هو جزء من السلسلة ويتناول كيفية إعداد عمليات التتبّع الموزعة في الخدمات المصغّرة باستخدام OpenTelemetry وCloud Trace. سيتناول الجزء الثاني إنشاء الملفات الشخصية باستمرار باستخدام Cloud Profiler.
تتبُّع الأداء الموزَّع
يُعد التتبع بين السجلات والمقاييس وعمليات التتبع، وهو القياس عن بُعد الذي يحدد وقت الاستجابة لجزء معين من العملية في النظام. وخاصة في عصر الخدمات المصغَّرة، تُعد عمليات التتبُّع الموزَّعة عاملاً قويًا في رصد المؤثِّرات السلبية في وقت الاستجابة في النظام الموزَّع بشكلٍ عام.
عند تحليل آثار الأنشطة الموزَّعة، يكون تمثيل بيانات التتبُّع هو المفتاح لفهم وقت الاستجابة العام للنظام بنظرة سريعة. في التتبُّع الموزع، نتعامل مع مجموعة من الطلبات لمعالجة طلب واحد لنقطة دخول النظام على شكل عملية تتبُّع تحتوي على عدة نطاقات.
يمثل المحيط وحدة فردية من العمل يتم إنجازه في نظام موزع، ويسجل أوقات البدء والتوقف. غالبًا ما يكون للامتدادات علاقات هرمية بين بعضها البعض - في الصورة أسفل كل امتدادات أصغر هي امتدادات فرعية لامتداد /رسائل كبير، ويتم تجميعها في تتبع واحد يُظهر مسار العمل من خلال أحد الأنظمة.
خدمة Google Cloud Trace هي أحد خيارات الواجهة الخلفية للتتبُّع الموزَّع، وهي متكاملة بشكلٍ جيد مع منتجات أخرى في Google Cloud.
ما الذي ستنشئه
في هذا الدرس التطبيقي حول الترميز، ستستخدم أدوات تتبع المعلومات في الخدمات التي يُطلق عليها اسم "تطبيق شكسبير" (تُعرف أيضًا باسم Shakesapp) تعمل على مجموعة Google Kubernetes Engine. يتم توضيح بنية Shakesapp أدناه:
- يرسل Loadgen سلسلة طلب بحث إلى العميل في HTTP
- يمر العملاء بالاستعلام من أداة التحميل إلى الخادم في gRPC
- يقبل الخادم طلب البحث من العميل، ويجلب جميع أعمال شكسبير بتنسيق نصي من Google Cloud Storage، ويبحث في الأسطر التي تحتوي على طلب البحث ويعرض عدد السطر المتطابق مع العميل.
وستستخدم معلومات التتبع عبر الطلب. بعد ذلك، ستقوم بتضمين وكيل محلّل في الخادم والتحقيق في المؤثِّر السلبي.
المعلومات التي ستطّلع عليها
- كيفية بدء استخدام مكتبات OpenTelemetry Trace في مشروع Go
- كيفية إنشاء فاصل باستخدام المكتبة
- كيفية نشر سياقات الامتداد عبر السلك بين مكونات التطبيق
- كيفية إرسال بيانات التتبُّع إلى Cloud Trace
- كيفية تحليل آثار الأنشطة على Cloud Trace
يشرح هذا الدرس التطبيقي كيفية إدارة الخدمات المصغَّرة. لتسهيل فهمه، يحتوي هذا المثال فقط على 3 مكونات (منشئ التحميل والعميل والخادم)، ولكن يمكنك تطبيق العملية نفسها الموضحة في هذا الدرس التطبيقي حول الترميز على أنظمة أكثر تعقيدًا وأكبر حجمًا.
المتطلبات
- معرفة أساسية بـ Go
- معلومات أساسية حول نظام Kubernetes
2. الإعداد والمتطلبات
إعداد بيئة ذاتية
إذا لم يكن لديك حساب Google (Gmail أو Google Apps)، يجب عليك إنشاء حساب. سجِّل الدخول إلى وحدة تحكُّم Google Cloud Platform ( console.cloud.google.com) وأنشئ مشروعًا جديدًا.
إذا كان لديك مشروع بالفعل، فانقر فوق القائمة المنسدلة لاختيار المشروع في أعلى يسار وحدة التحكم:
وانقر على "مشروع جديد" في مربع الحوار الناتج لإنشاء مشروع جديد:
إذا لم يكن لديك مشروع، من المفترض أن يظهر لك مربع حوار مثل هذا لإنشاء مشروعك الأول:
يتيح لك مربع الحوار اللاحق لإنشاء المشروع إدخال تفاصيل مشروعك الجديد:
يُرجى تذكُّر رقم تعريف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (سبق أن تم استخدام الاسم أعلاه ولن يكون مناسبًا لك). ستتم الإشارة إليه لاحقًا في هذا الدرس التطبيقي حول الترميز باسم PROJECT_ID.
بعد ذلك، عليك تفعيل الفوترة في Developers Console لاستخدام موارد Google Cloud وتفعيل Cloud Trace API إذا لم يسبق لك إجراء ذلك.
لا ينبغي أن يكلفك هذا الدرس التطبيقي أكثر من بضعة دولارات، ولكن قد تزيد التكاليف إذا قررت استخدام المزيد من الموارد أو إذا تركتها قيد التشغيل (راجع قسم "التنظيف" في نهاية هذا المستند). وتتم الإشارة إلى أسعار Google Cloud Trace وGoogle Kubernetes Engine وGoogle Artifact Registry في المستندات الرسمية.
- أسعار حزمة عمليات Google Cloud | حزمة العمليات
- التسعير | مستندات Kubernetes Engine
- أسعار Artifact Registry | مستندات Artifact Registry
إنّ مستخدمي Google Cloud Platform الجدد مؤهّلون للاستفادة من فترة تجريبية مجانية بقيمة 300 دولار أمريكي، ما يجعل هذا الدرس التطبيقي حول الترميز بدون أي تكلفة.
إعداد Google Cloud Shell
يمكن إدارة Google Cloud وGoogle Cloud Trace عن بُعد من الكمبيوتر المحمول، ولكن في هذا الدرس التطبيقي حول الترميز، سنستخدم Google Cloud Shell، وهي بيئة سطر أوامر يتم تشغيلها في السحابة الإلكترونية.
هذا الجهاز الافتراضي المستند إلى نظام دبيان محمل بكل أدوات التطوير التي ستحتاج إليها. وتوفّر هذه الشبكة دليلاً رئيسيًا دائمًا بسعة 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 Artifact Registry (GAR)
- نشر الحاويات على GKE
- تعديل رمز المصدر للخدمات من أجل أداة التتبُّع
- الانتقال إلى الخطوة 2
تفعيل Kubernetes Engine
أولاً، أعددنا مجموعة Kubernetes حيث يتم تشغيل Shakesapp على GKE، لذلك نحتاج إلى تفعيل GKE. الانتقال إلى القائمة "Kubernetes Engine" والضغط على زر "تفعيل"
أصبحت الآن جاهزًا لإنشاء مجموعة Kubernetes.
إنشاء مجموعة Kubernetes
في Cloud Shell، شغِّل الأمر التالي لإنشاء مجموعة Kubernetes. يُرجى التأكد من أنّ قيمة المنطقة تقع ضمن المنطقة التي ستستخدمها لإنشاء مستودع Artifact Registry. يمكنك تغيير قيمة المنطقة 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
إعداد Artifact Registry وSaffold
لدينا الآن مجموعة Kubernetes جاهزة للنشر. بعد ذلك، نستعد لسجل الحاويات لإرسال الحاويات ونشرها. لتنفيذ هذه الخطوات، نحتاج إلى إعداد Artifact Registry (GAR) وجدول بيانات لاستخدامه.
إعداد Artifact Registry
الانتقال إلى قائمة Artifact Registry والضغط على زر "تفعيل"
بعد لحظات، سيظهر لك متصفّح مستودع GAR. انقر على "إنشاء مستودع" وإدخال اسم المستودع.
في هذا الدرس التطبيقي حول الترميز، أسمي المستودع الجديد باسم trace-codelab
. تنسيق العنصر هو "Docker" ونوع الموقع الجغرافي هو "المنطقة". اختَر المنطقة القريبة من المنطقة التي ضبطتها للمنطقة التلقائية في Google Compute Engine. فعلى سبيل المثال، اختار هذا المثال "us-central1-f" أعلاه، لذلك نختار هنا "us-central1 (آيوا)". ثم انقر فوق زر "CREATE" .
ستظهر لك الآن رسالة "trace-codelab" على متصفح المستودع.
سنعود إلى هذه الصفحة لاحقًا للتحقّق من مسار السجلّ.
إعداد سافلات
تعتبر خدمة Skaffold أداة مفيدة عند العمل على إنشاء خدمات مصغّرة يتم تشغيلها على Kubernetes. فهو يعالج سير عمل إنشاء حاويات التطبيقات ودفعها ونشرها باستخدام مجموعة صغيرة من الأوامر. يستخدم Skaffold بشكل افتراضي Docker Registry كسجل للحاويات، لذا يجب إعداد skaffold للتعرّف على GAR عند إرسال الحاويات إليه.
افتح Cloud Shell مرة أخرى وتأكَّد مما إذا كان قد تم تثبيت skaffold. (تثبّت Cloud Shell برنامج التخزين في البيئة تلقائيًا.) شغّل الأمر التالي وشاهد إصدار skaffold.
skaffold version
مخرجات الأمر
v1.38.0
الآن، يمكنك تسجيل المستودع الافتراضي لاستخدام Saffold. للحصول على مسار السجلّ، انتقِل إلى لوحة بيانات Artifact Registry وانقر على اسم المستودع الذي أعددته للتو في الخطوة السابقة.
بعد ذلك، ستظهر لك مسارات التنقل في أعلى الصفحة. انقر على الرمز لنسخ مسار قاعدة بيانات المسجّلين إلى الحافظة.
عند النقر على الزر "نسخ"، يظهر مربّع حوار في أسفل المتصفّح يعرض رسالة مثل:
"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 حيث يتم تشغيل الخدمات المصغَّرة للدروس التطبيقية حول الترميز
التالي
الخطوة التالية هي إنشاء الخدمات المصغَّرة ونشرها ونشرها على المجموعة
3- إنشاء الخدمات المصغّرة ونشرها ونشرها
تنزيل مواد الدرس التطبيقي حول الترميز
في الخطوة السابقة، حدّدنا جميع المتطلّبات الأساسية لهذا الدرس التطبيقي حول الترميز. أنت الآن جاهز لتشغيل خدمات مصغّرة بالكامل فوقها. تتم استضافة مواد الدرس التطبيقي على 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: تعريف Proto للاتصال بين العميل والخادم
- src: أدلة لرمز المصدر لكل خدمة
- skaffold.yaml: ملف الإعداد لـ skaffold
في هذا الدرس التطبيقي، ستُعدِّل رمز المصدر المتوفّر ضمن مجلد "step0
". يمكنك أيضًا الرجوع إلى رمز المصدر في step[1-6]
مجلد للحصول على الإجابات من خلال الخطوات التالية. (يغطي الجزء 1 الخطوة 0 إلى 4، في حين يتناول الجزء الثاني الخطوة 5 و6)
تشغيل أمر skaffold
وأخيرًا، أصبحت جاهزًا لإنشاء المحتوى ونشره ونشره في مجموعة Kubernetes التي أنشأتها للتو. يبدو هذا وكأنه يحتوي على خطوات متعددة لكن العنصر الفعلي هو سقالة يقوم بكل شيء نيابة عنك. لنجرب ذلك باستخدام الأمر التالي:
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
بعد النشر، سترى سجلات التطبيق الفعلية المنبعثة إلى تنسيق stdout في كل حاوية على النحو التالي:
مخرجات الأمر
[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
ملخّص
في هذه الخطوة، تكون قد أعددت مواد التمرين المعملي حول الترميز في بيئتك وتأكدت من تشغيل سقالة على النحو المتوقع.
التالي
في الخطوة التالية، ستقوم بتعديل الرمز المصدر لخدمة التحميل لقياس معلومات التتبع.
4. قياس حالة HTTP
مفهوم أدوات التتبع والانتشار
قبل تعديل رمز المصدر، دعوني أن أشرح بإيجاز كيفية عمل إشارات التتبّع الموزعة في رسم تخطيطي بسيط.
في هذا المثال، نستخدم الرمز البرمجي لتصدير معلومات التتبع والمساحة إلى خدمة Cloud Trace وننشر سياقها عبر الطلب من خدمة مجموعة التحميل إلى خدمة الخادم.
تحتاج التطبيقات إلى إرسال البيانات الوصفية للتتبُّع مثل "رقم تعريف التتبُّع" و"رقم تعريف النطاق" (Span ID) لتجميع جميع النطاقات التي تحتوي على "معرّف التتبُّع" (Trace) نفسه في عملية تتبُّع واحدة. وعلى التطبيق أيضًا نشر سياقات التتبع (مزيج من معرّف التتبع ومعرّف Span للنطاق الرئيسي) عند طلب خدمات المراحل الأخيرة، حتى يكون على دراية بسياق التتبع الذي يعالجه.
يساعدك OpenTelemetry على:
- لإنشاء رقم تعريف تتبّع فريد ومعرّف نطاق زمني
- لتصدير "رقم تعريف التتبُّع" و"رقم تعريف النطاق" (Span ID) إلى الواجهة الخلفية
- لنشر سياقات التتبع في الخدمات الأخرى
- لتضمين بيانات وصفية إضافية تساعد في تحليل الآثار
المكوّنات في OpenTelemetry Trace
في ما يلي عملية حساب أداة تتبع التطبيقات باستخدام OpenTelemetry:
- إنشاء جهة تصدير
- قم بإنشاء TracerProvider لربط المصدِّر في 1 وتعيينه على مستوى العالم.
- اضبط TextMapPropagaror لضبط طريقة النشر
- الحصول على برنامج التتبُّع من TracerProvider
- إنشاء نطاق من أداة التتبع
في الوقت الحالي، لا تحتاج إلى فهم الخصائص التفصيلية في كل مكوّن، ولكن الشيء الأهم الذي يجب تذكره هو:
- يمكن توصيل المصدِّر هنا إلى TracerProvider.
- يحتفظ TracerProvider بجميع الإعدادات المتعلقة بتحليل عيّنات البيانات والتصدير.
- يتم تجميع كل الآثار في كائن التتبع
وبفهم هذا الأمر، لننتقل إلى عملية الترميز الفعلية.
المسافة الأولى للأداة
خدمة إنشاء معدّات تحميل الآلات
افتح محرِّر Cloud Shell بالضغط على الزر في أعلى يسار Cloud Shell. افتح
step0/src/loadgen/main.go
من المستكشف في اللوحة اليمنى وابحث عن الدالة الرئيسية.
step0/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
فيها. في عملية التنفيذ الحالية، يحتوي القسم على سطرَي سجلّ يسجِّلان بداية استدعاء الدالة ونهايته. والآن، لنستخدم معلومات Span لتتبع وقت استجابة استدعاء الدالة.
أولاً، كما هو موضح في القسم السابق، لنقم بإعداد التهيئات الكاملة لـ OpenTelemetry. أضف حزم OpenTelemetry على النحو التالي:
step0/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
.
step0/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
الذي يصدِّر جميع معلومات التتبُّع إلى ملف stdout بتنسيق منظَّم.
ثم تقوم باستقاله من الدالة الرئيسية. يمكنك الاتصال برقم initTracer()
والحرص على الاتصال بالرقم TracerProvider.Shutdown()
عند إغلاق التطبيق.
step0/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) ...
وبعد الانتهاء من الإعداد، يجب إنشاء Span بمعرّف Trace ومعرّف Span فريدَين. يوفر OpenTelemetry مكتبة مفيدة. إضافة حزم جديدة إضافية إلى عميل HTTP للأداة.
step0/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 عبر البرنامج الذي تم قياسه.
step0/src/loadgen/main.go
var httpClient = http.Client{ Transport: otelhttp.NewTransport(http.DefaultTransport) }
بعد ذلك، أضِف الأداة في الدالة runQuery
لإنشاء مدى مخصّص باستخدام OpenTelemetry، والنطاق الذي يتم إنشاؤه تلقائيًا من برنامج HTTP المخصّص. ما ستفعله هو:
- الحصول على تطبيق Tracer من "
TracerProvider
" على مستوى العالم باستخدام "otel.Tracer()
" - إنشاء نطاق جذر باستخدام طريقة
Tracer.Start()
- إنهاء امتداد الجذر بتنسيق عشوائي (في هذه الحالة، نهاية الدالة
runQuery
)
step0/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) }
لقد انتهيت الآن من استخدام الأداة في أداة تحميل (تطبيق عميل HTTP). يُرجى تعديل go.mod
وgo.sum
باستخدام الأمر go mod
.
go mod tidy
خدمة عملاء الأدوات
في القسم السابق، قمنا بقياس الجزء المحصور في المستطيل الأحمر في الرسم أدناه. قمنا بتجهيز معلومات الامتداد في خدمة منشئ الحمولة. على غرار خدمة منشئ التحميل، نحتاج الآن إلى ضبط خدمة العميل. الاختلاف عن خدمة منشئ التحميل هو أن خدمة العميل تحتاج إلى استخراج معلومات معرف التتبع التي تم نشرها من خدمة منشئ التحميل في رأس HTTP واستخدام المعرف لإنشاء Spans.
افتح محرِّر Cloud Shell وأضِف الحزم المطلوبة كما فعلنا مع خدمة منشئ الحِمل.
step0/src/client/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
في خدمة العميل أيضًا.
step0/src/client/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
كما فعلت في أداة التحميل.
أولاً، نستبدل تسجيل المعالج بمعالج otelhttp
. في الدالة main
، ابحث عن الأسطر التي تم فيها تسجيل معالج HTTP من خلال http.HandleFunc()
.
step0/src/client/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)
ثم، نحسب التباعد الفعلي داخل المعالج. ابحث عن Fanc (*clientService) recordr()، وأضِف أداة المدى من خلال trace.SpanFromContext()
.
step0/src/client/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)) ...
باستخدام كل الأدوات الواردة أعلاه، أكملت أداة التتبُّع بين أداة التحميل والعميل. لنفهم طريقة عملها. قم بتشغيل التعليمة البرمجية باستخدام 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
هذه الرسائل. ستلاحظ أنّ عناصر الأساس لكل النطاقات من خلال مُنشئ التحميل لها TraceID: 00000000000000000000000000000000
، لأن هذا هو نطاق الجذر، أي الامتداد الأول في التتبع. ستلاحظ أيضًا أنّ سمة التضمين "query"
تحتوي على سلسلة طلب البحث التي تم ضبطها على خدمة العميل.
ملخّص
في هذه الخطوة، تكون قد أعددت خدمة منشئ التحميل وخدمة العميل التي تتصل في HTTP وأكّدت أنه يمكنك نشر Trace Context عبر الخدمات بنجاح وتصدير معلومات Span من كلتا الخدمتين إلى stdout.
التالي
في الخطوة التالية، ستستعين بخدمة العميل وخدمة الخادم لتأكيد كيفية نشر Trace Context عبر gRPC.
5- قياس حالة gRPC
في الخطوة السابقة، تم قياس النصف الأول من الطلب في هذه الخدمات المصغَّرة. في هذه الخطوة، نحاول استخدام اتصال gRPC بين خدمة العميل وخدمة الخادم. (مستطيل أخضر وأرجواني في الصورة أدناه)
إنشاء الأدوات مسبقًا لعميل gRPC
يوفر نظام OpenTelemetry الشامل الكثير من المكتبات المفيدة التي تساعد مطوري البرامج في قياس أداء التطبيقات. في الخطوة السابقة، استخدمنا أداة ما قبل الإنشاء لحزمة net/http
. في هذه الخطوة، بينما نحاول نشر سياق "Trace Context" من خلال gRPC، نستخدم المكتبة لذلك.
أولاً، يمكنك استيراد حزمة gRPC المنشأة مسبقًا والتي تسمى otelgrpc
.
step0/src/client/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 التي تسجّل امتدادات جديدة في كل مرة يرسل فيها العميل طلبات إلى الخادم.
step0/src/client/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. أضف حزمة جديدة إلى قسم الاستيراد مثل:
step0/src/server/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 أولاً، تمامًا كما فعلت في خدمة إنشاء التحميل وخدمات العملاء.
step0/src/server/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()
وأضِف عناصر اعتراض إلى الدالة.
step0/src/server/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
الآن مرة أخرى، ترى مجموعة من معلومات الامتداد على stdout.
مخرجات الأمر
... [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 في سهولة التوصيل. لعرض جميع النطاقات التي تجمعها أداتك، ما عليك سوى استبدال أداة تصدير البيانات الثابتة بأداة تصدير Cloud Trace.
افتح ملفات main.go
لكل خدمة، وابحث عن الدالة initTracer()
. احذف السطر لإنشاء مصدِّر stdout وأنشئ جهة تصدير Cloud Trace بدلاً من ذلك.
step0/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
وبذلك لن يظهر لك الآن الكثير من معلومات الامتداد بتنسيق السجلات المنظَّمة على stdout، لأنّك استبدلت المُصدِّر بأداة Cloud Trace one.
مخرجات الأمر
[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 Console وانتقِل إلى "قائمة التتبُّع". من السهل الوصول إليها من مربع البحث. بخلاف ذلك، يمكنك النقر على القائمة في اللوحة اليمنى.
ثم ترى الكثير من النقاط الزرقاء موزعة عبر الرسم البياني لوقت الاستجابة. وتمثّل كل نقطة آثار واحدة.
انقر على أحدهما للاطّلاع على التفاصيل داخل عملية التتبُّع.
حتى من خلال هذه النظرة السريعة البسيطة، تعرف بالفعل الكثير من الأفكار. على سبيل المثال، من الرسم البياني الانحداري، يمكنك معرفة أن سبب وقت الاستجابة يرجع في الغالب إلى الامتداد المسمى shakesapp.ShakespeareService/GetMatchCount
. (انظر 1 في الصورة أعلاه) يمكنك تأكيد ذلك من جدول الملخص. (يوضح العمود في أقصى اليمين مدة كل نطاق). بالإضافة إلى ذلك، كانت عملية التتبّع هذه مرتبطة بطلب البحث "friend". (انظر 2 في الصورة أعلاه)
في ضوء هذه التحليلات القصيرة، قد تدرك أنك بحاجة إلى معرفة مسافات أكثر دقة داخل طريقة GetMatchCount
. بالمقارنة مع معلومات stdout، يعد التصور قويًا. لمزيد من المعلومات عن تفاصيل Cloud Trace، يُرجى الانتقال إلى مستنداتنا الرسمية.
ملخّص
في هذه الخطوة، استبدلت مُصدِّر stdout بخدمة Cloud Trace one وعمليات تتبُّع مرئية على Cloud Trace. كما تعلمت كيفية البدء في تحليل الآثار.
التالي
في الخطوة التالية، ستقوم بتعديل رمز المصدر لخدمة الخادم لإضافة نطاق فرعي في GetMatchCount.
7. إضافة نطاق فرعي لإجراء تحليل أفضل
في الخطوة السابقة، وجدتَ أنّ سبب وقت إرسال البيانات ذهابًا وإيابًا من خلال أداة التحميل هو في الغالب العملية داخل طريقة GetMatchCount، معالج gRPC، في خدمة الخادم. ومع ذلك، نظرًا لأننا لم نستند إلى أي أداة سوى المعالج، لا يمكننا العثور على مزيد من الإحصاءات من الرسم البياني للعرض الإعلاني بدون انقطاع. هذه حالة شائعة عندما نبدأ في قياس حالة الخدمات المصغَّرة.
في هذا القسم، سنبحث عن أي مدى فرعي يستدعي الخادم Google Cloud Storage لأنّه من الشائع أن تستغرق بعض عمليات إدخال/إخراج الشبكة الخارجية وقتًا طويلاً في العملية ومن المهم تحديد ما إذا كان السبب هو الاتصال.
أداة المسافة الفرعية في الخادم
افتح main.go
في الخادم وابحث عن الدالة readFiles
. تطلب هذه الدالة طلبًا إلى Google Cloud Storage لجلب جميع الملفات النصية لأعمال شكسبير. في هذه الدالة، يمكنك إنشاء نطاق فرعي، مثل ما فعلته لقياس أدوات خادم HTTP في خدمة العميل.
step0/src/server/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
) كيف يمكنك فلترة هذه المسافات من ميزة "تتبُّع السحابة الإلكترونية"؟ يمكنك الاطّلاع على التلميح هنا. - يمكنك ربط سجلات الأحداث بالامتدادات ومعرفة كيفية عملها على 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
بعد حذف المجموعة، حدِّد "إدارة الهوية وإمكانية الوصول المشرف" > "الإعدادات"، ثم النقر على "إيقاف الصوت" .
بعد ذلك، أدخِل رقم تعريف المشروع (وليس اسم المشروع) في النموذج الوارد في مربّع الحوار وأكِّد إيقاف التشغيل.