أداة لتحسين أداء تطبيقك في Go (الجزء 2: المحلّل)

1. مقدمة

e0509e8a07ad5537.png

تاريخ آخر تعديل: 14/07/2022

إمكانية تتبّع التطبيق

إمكانية الملاحظة والمحلل المستمر

الملاحظة هي المصطلح المستخدم لوصف سمة أي نظام. يسمح النظام مع إمكانية الملاحظة للفرق بتصحيح أخطاء نظامهم بشكل نشط. وفي هذا السياق، توجد ثلاث ركائز للملاحظة؛ والسجلات والمقاييس والتتبعات هي الأدوات الأساسية التي يستخدمها النظام لاكتساب إمكانية الملاحظة.

بالإضافة إلى الركائز الثلاث للملاحظة، يُعدّ التحليل المستمر عنصرًا رئيسيًا آخر في إمكانية الملاحظة وتوسيع قاعدة المستخدمين في المجال. أداة Cloud Profiler هي إحدى أدوات الإنشاء وتوفّر واجهة سهلة للتوغّل في مقاييس الأداء في حِزم طلبات التطبيقات.

هذا الدرس التطبيقي هو الجزء الثاني من السلسلة ويتناول كيفية إعداد أداة تحليل مستمر. يتناول الجزء الأول عملية التتبّع الموزعة باستخدام OpenTelemetry وCloud Trace، وستتعرف على المزيد من المعلومات حول تحديد المؤثِّرات السلبية للخدمات المصغّرة بشكل أفضل من خلال الجزء 1.

ما الذي ستنشئه

في هذا الدرس التطبيقي حول الترميز، ستستخدم أداة وكيل المحلّل المستمر في خدمة الخادم الخاصة بتطبيق "Shakespeare" (تُعرف أيضًا باسم Shakesapp) تعمل على مجموعة Google Kubernetes Engine. يتم توضيح بنية Shakesapp أدناه:

44e243182ced442f.png

  • يرسل Loadgen سلسلة طلب بحث إلى العميل في HTTP
  • يمر العملاء بالاستعلام من أداة التحميل إلى الخادم في gRPC
  • يقبل الخادم طلب البحث من العميل، ويجلب جميع أعمال شكسبير بتنسيق نصي من Google Cloud Storage، ويبحث في الأسطر التي تحتوي على طلب البحث ويعرض عدد السطر المتطابق مع العميل.

في الجزء 1، وجدت أن المعوقات موجودة في مكان ما في خدمة الخادم، ولكن لم تتمكن من تحديد السبب الدقيق.

المعلومات التي ستطّلع عليها

  • كيفية تضمين وكيل المحلّل
  • طريقة التحقق من المشكلة في "أداة تحليل بيانات Cloud"

يشرح هذا الدرس التطبيقي حول الترميز كيفية التعامل مع وكيل محلّل مستمر في تطبيقك.

المتطلبات

  • معرفة أساسية بـ Go
  • معلومات أساسية حول نظام Kubernetes

2. الإعداد والمتطلبات

إعداد بيئة ذاتية

إذا لم يكن لديك حساب Google (Gmail أو Google Apps)، يجب عليك إنشاء حساب. سجِّل الدخول إلى وحدة تحكُّم Google Cloud Platform ( console.cloud.google.com) وأنشئ مشروعًا جديدًا.

إذا كان لديك مشروع بالفعل، فانقر فوق القائمة المنسدلة لاختيار المشروع في أعلى يسار وحدة التحكم:

7a32e5469db69e9.png

وانقر فوق "مشروع جديد" في مربع الحوار الناتج لإنشاء مشروع جديد:

7136b3ee36ebaf89.png

إذا لم يكن لديك مشروع، من المفترض أن يظهر لك مربّع حوار مثل هذا لإنشاء مشروعك الأول:

870a3cbd6541ee86.png

يتيح لك مربع الحوار اللاحق لإنشاء المشروع إدخال تفاصيل مشروعك الجديد:

affdc444517ba805.png

يُرجى تذكُّر رقم تعريف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (سبق أن تم استخدام الاسم أعلاه ولن يكون مناسبًا لك). ستتم الإشارة إليه لاحقًا في هذا الدرس التطبيقي حول الترميز باسم PROJECT_ID.

بعد ذلك، عليك تفعيل الفوترة في Developers Console لاستخدام موارد Google Cloud وتفعيل Cloud Trace API إذا لم يسبق لك إجراء ذلك.

15d0ef27a8fbab27.png

لن يكلفك تنفيذ هذا الدرس التطبيقي أكثر من بضعة دولارات، ولكن قد تزيد التكاليف إذا قررت استخدام المزيد من الموارد أو إذا تركتها قيد التشغيل (يُرجى الاطّلاع على قسم "التنظيف" في نهاية هذا المستند). وتتم الإشارة إلى أسعار Google Cloud Trace وGoogle Kubernetes Engine وGoogle 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 gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A (من المفترَض أن تستغرق عملية الإعداد والاتصال بالبيئة بضع دقائق فقط).

JjEuRXGg0AYYIY6QZ8d-66gx_Mtc-_jDE9ijmbXLJSAXFvJt-qUpNtsBsYjNpv2W6BQSrDc1D-ARINNQ-1EkwUhz-iUK-FUCZhJ-NtjvIEx9pIkE-246DomWuCfiGHK78DgoeWkHRw

لقطة شاشة يوم 14-06-2017 في الساعة 10.13.43 مساءً.png

بعد الربط بتطبيق 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:

158fNPfwSxsFqz9YbtJVZes8viTS3d1bV4CVhij3XPxuzVFOtTObnwsphlm6lYGmgdMFwBJtc-FaLrZU7XHAg_ZYoCrgombMRR3h-eolLPcvO351c5iBv506B3ZwghZoiRg6cz23Qw

تضبط 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). في ما يلي خطوات هذا الدرس التطبيقي:

  1. تنزيل المشروع الأساسي في Cloud Shell
  2. إنشاء خدمات مصغّرة في حاويات
  3. تحميل الحاويات إلى Google Artifact Registry (GAR)
  4. نشر الحاويات على GKE
  5. تعديل رمز المصدر للخدمات من أجل أداة التتبُّع
  6. الانتقال إلى الخطوة 2

تفعيل Kubernetes Engine

أولاً، أعددنا مجموعة Kubernetes حيث يتم تشغيل Shakesapp على GKE، لذلك نحتاج إلى تفعيل GKE. الانتقال إلى القائمة "Kubernetes Engine" والضغط على زر "تفعيل"

548cfd95bc6d344d.png

أصبحت الآن جاهزًا لإنشاء مجموعة 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 والضغط على زر "تفعيل"

45e384b87f7cf0db.png

بعد لحظات، سيظهر لك متصفّح مستودع GAR. انقر على "إنشاء مستودع" وإدخال اسم المستودع.

d6a70f4cb4ebcbe3.png

في هذا الدرس التطبيقي حول الترميز، أسمي المستودع الجديد باسم trace-codelab. تنسيق العنصر هو "Docker" ونوع الموقع الجغرافي هو "المنطقة". اختَر المنطقة القريبة من المنطقة التي ضبطتها للمنطقة التلقائية في Google Compute Engine. فعلى سبيل المثال، اختار هذا المثال "us-central1-f" أعلاه، لذلك نختار هنا "us-central1 (آيوا)". ثم انقر فوق زر "CREATE" .

9c2d1ce65258ef70.png

ستظهر لك الآن رسالة "trace-codelab" على متصفح المستودع.

7a3c1f47346bea15.png

سنعود إلى هذه الصفحة لاحقًا للتحقّق من مسار السجلّ.

إعداد سافلات

تعتبر خدمة Skaffold أداة مفيدة عند العمل على إنشاء خدمات مصغّرة يتم تشغيلها على Kubernetes. فهو يعالج سير عمل إنشاء حاويات التطبيقات ودفعها ونشرها باستخدام مجموعة صغيرة من الأوامر. يستخدم Skaffold بشكل افتراضي Docker Registry كسجل للحاويات، لذا يجب إعداد skaffold للتعرّف على GAR عند إرسال الحاويات إليه.

افتح Cloud Shell مرة أخرى وتأكَّد مما إذا كان قد تم تثبيت skaffold. (تثبّت Cloud Shell برنامج التخزين في البيئة تلقائيًا.) شغّل الأمر التالي وشاهد إصدار skaffold.

skaffold version

مخرجات الأمر

v1.38.0

الآن، يمكنك تسجيل المستودع الافتراضي لاستخدام Saffold. للحصول على مسار السجلّ، انتقِل إلى لوحة بيانات Artifact Registry وانقر على اسم المستودع الذي أعددته للتو في الخطوة السابقة.

7a3c1f47346bea15.png

بعد ذلك، ستظهر لك مسارات التنقل في أعلى الصفحة. انقر على الرمز e157b1359c3edc06.png لنسخ مسار قاعدة بيانات المسجّلين إلى الحافظة.

e0f2ae2144880b8b.png

عند النقر على الزر "نسخ"، يظهر مربّع حوار في أسفل المتصفّح يعرض رسالة مثل:

&quot;us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab&quot; تم نسخ

ارجع إلى هيكل السحابة الإلكترونية. نفِّذ الأمر 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

في هذا الدرس التطبيقي، ستُعدِّل رمز المصدر المتوفّر ضمن مجلد "step4". يمكنك أيضًا الرجوع إلى رمز المصدر في step[1-6] مجلد للاطّلاع على التغييرات من البداية. (يغطي الجزء 1 الخطوة 0 إلى 4، في حين يتناول الجزء الثاني الخطوة 5 و6)

تشغيل أمر skaffold

وأخيرًا، أصبحت جاهزًا لإنشاء المحتوى ونشره ونشره في مجموعة Kubernetes التي أنشأتها للتو. يبدو هذا وكأنه يحتوي على خطوات متعددة لكن العنصر الفعلي هو سقالة يقوم بكل شيء نيابة عنك. لنجرب ذلك باستخدام الأمر التالي:

cd step4
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. قياس حالة وكيل "أداة تحليل البيانات في السحابة الإلكترونية"

مفهوم التحليل المستمر

قبل شرح مفهوم التحليل المستمر، نحتاج إلى فهم مفهوم إنشاء الملفات التعريفية أولاً. يُعد إنشاء المواصفات التعريفية إحدى طرق تحليل التطبيق ديناميكيًا (تحليل البرنامج الديناميكي) وعادة ما يتم تنفيذه أثناء تطوير التطبيق في عملية اختبار التحميل وما إلى ذلك. هذا نشاط لقطة واحدة لقياس مقاييس النظام، مثل وحدة المعالجة المركزية (CPU) واستخدامات الذاكرة، خلال الفترة المحددة. بعد جمع بيانات الملف الشخصي، يحللها المطورون خارج التعليمات البرمجية.

التحليل المستمر هو أسلوب موسّع لعملية إنشاء الملفات التعريفية العادية: فهي تشغِّل ملفات شخصية للنافذة القصيرة مقابل التطبيق الذي يعمل لفترة طويلة بشكل دوري وتجمع مجموعة من بيانات الملفات الشخصية. بعد ذلك، تنشئ الخدمة التحليل الإحصائي تلقائيًا استنادًا إلى سمة معيّنة للتطبيق، مثل رقم الإصدار ومنطقة النشر ووقت القياس وما إلى ذلك. يمكنك العثور على المزيد من التفاصيل حول هذا المفهوم في مستنداتنا.

ونظرًا لأن الهدف عبارة عن تطبيق قيد التشغيل، فهناك طريقة لجمع بيانات الملف الشخصي بشكل دوري وإرسالها إلى الواجهة الخلفية التي بعد معالجة البيانات الإحصائية. هذا هو وكيل Cloud Profiler وسيتم تضمينه في خدمة الخادم قريبًا.

تضمين وكيل Cloud Profiler

افتح محرِّر Cloud Shell بالضغط على الزر 776a11bfb2122549.png في أعلى يسار Cloud Shell. افتح step4/src/server/main.go من المستكشف في اللوحة اليمنى وابحث عن الدالة الرئيسية.

step4/src/server/main.go

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

        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)
        healthpb.RegisterHealthServer(srv, svc)
        if err := srv.Serve(lis); err != nil {
                log.Fatalf("error serving server: %v", err)
        }
}

في الدالة main، ستلاحظ بعض رموز إعداد OpenTelemetry وgRPC التي تم تنفيذها في الجزء الأول من الدرس التطبيقي حول الترميز. يمكنك الآن إضافة أدوات لوكيل Cloud Profiler هنا. مثلما فعلنا مع initTracer()، يمكنك كتابة دالة تُسمى initProfiler() لتسهيل القراءة.

step4/src/server/main.go

import (
        ...
        "cloud.google.com/go/profiler" // step5. add profiler package
        "cloud.google.com/go/storage"
        ...
)

// step5: add Profiler initializer
func initProfiler() {
        cfg := profiler.Config{
                Service:              "server",
                ServiceVersion:       "1.0.0",
                NoHeapProfiling:      true,
                NoAllocProfiling:     true,
                NoGoroutineProfiling: true,
                NoCPUProfiling:       false,
        }
        if err := profiler.Start(cfg); err != nil {
                log.Fatalf("failed to launch profiler agent: %v", err)
        }
}

لنلقِ نظرة عن كثب على الخيارات المحدّدة في الكائن profiler.Config{}.

  • الخدمة: اسم الخدمة التي يمكنك اختيارها وتفعيل لوحة بيانات المحلّل
  • ServiceVersion: اسم إصدار الخدمة. يمكنك مقارنة مجموعات بيانات الملف الشخصي استنادًا إلى هذه القيمة.
  • NoHeapProfiling: إيقاف تحليل استهلاك الذاكرة
  • NoAllocProfiling: إيقاف تحليل تخصيص الذاكرة
  • NoGoroutineProfiling: إيقاف التحليل الصارم
  • NoCPUProfiling: إيقاف تحليل وحدة المعالجة المركزية (CPU)

في هذا الدرس التطبيقي حول الترميز، لا نفعِّل سوى تحليل وحدة المعالجة المركزية (CPU).

ما عليك الآن سوى استدعاء هذه الدالة في الدالة main. تأكَّد من استيراد حزمة Cloud Profiler في كتلة الاستيراد.

step4/src/server/main.go

func main() {
        ...
        defer func() {
                if err := tp.Shutdown(context.Background()); err != nil {
                        log.Fatalf("error shutting down TracerProvider: %v", err)
                }
        }()
        // step2. end setup

        // step5. start profiler
        go initProfiler()
        // step5. end

        svc := NewServerService()
        // step2: add interceptor
        ...
}

لاحظ أنك تستدعي الدالة initProfiler() مع الكلمة الرئيسية go. لأنّ "profiler.Start()" تحظره، لذا عليك تشغيله في مستوى روتيني آخر الآن هو جاهز للبناء. تأكَّد من تشغيل "go mod tidy" قبل النشر.

go mod tidy

ويمكنك الآن نشر مجموعتك باستخدام خدمة الخادم الجديدة.

skaffold dev

يستغرق عادةً ظهور الرسم البياني للشعب على Cloud Profiler بضع دقائق. اكتب "profiler" في مربع البحث أعلى الصفحة وانقر على رمز المحلل.

3d8ca8a64b267a40.png

ستشاهد بعد ذلك الرسم البياني للشعب التالي.

7f80797dddc0128d.png

ملخّص

في هذه الخطوة، تم تضمين وكيل Cloud Profiler في خدمة الخادم والتأكُّد من أنّه يُنشئ رسمًا بيانيًا لرسم متوهّج.

التالي

في الخطوة التالية، ستقوم بالتحقيق في سبب المؤثِّرة السلبية في التطبيق باستخدام الرسم البياني للشعب.

5- تحليل الرسم البياني المضغوط لأداة تحليل السحابة الإلكترونية

ما هو Flame Graph؟

Flame Graph هي إحدى طرق تصور بيانات الملف الشخصي. للحصول على شرح تفصيلي، يُرجى الرجوع إلى مستندنا، ولكن الملخّص الموجز هو:

  • يعبر كل شريط عن استدعاء الطريقة/الدالة في التطبيق
  • الاتجاه الرأسي هو حزمة الاستدعاء؛ حزمة الطلبات تنمو من أعلى إلى أسفل
  • الاتجاه الأفقي هو استخدام الموارد؛ كلما طالت، كان ذلك أسوأ.

بناءً على ذلك، لنلقِ نظرة على الرسم البياني للهب الذي تم الحصول عليه.

7f80797dddc0128d.png

تحليل الرسم البياني للشعب

في القسم السابق، تعلمت أن كل شريط في الرسم البياني للشعلة يعبر عن استدعاء الدالة/الطريقة، وطوله يعني استخدام المورد في الدالة/الطريقة. يعمل الرسم البياني اللهب في Cloud Profiler على ترتيب الشريط تنازليًا أو بالطول من اليسار إلى اليمين، ويمكنك بدء النظر إلى أعلى يمين الرسم البياني أولاً.

6d90760c6c1183cd.png

في حالتنا، يتّضح أنّ grpc.(*Server).serveStreams.func1.2 يستهلك معظم وقت وحدة المعالجة المركزية (CPU)، وبالنظر إلى حزمة الاتصال من الأعلى إلى الأسفل، يتم قضاء معظم الوقت في main.(*serverService).GetMatchCount، وهو معالِج خادم gRPC في خدمة الخادم.

ضمن GetMatchCount، تظهر لك سلسلة من دوال regexp: regexp.MatchString وregexp.Compile. إنها من الحزمة القياسية: أي أنه يجب اختبارها جيدًا من العديد من وجهات النظر، بما في ذلك الأداء. أمّا النتيجة هنا، فهي أنّ استخدام موارد وقت وحدة المعالجة المركزية (CPU) مرتفع في regexp.MatchString وregexp.Compile. بالنظر إلى هذه الحقائق، الافتراض هنا هو أنّ استخدام regexp.MatchString مرتبط بمشاكل في الأداء. لذا، هيا نقرأ رمز المصدر حيث يتم استخدام الدالة.

step4/src/server/main.go

func (s *serverService) GetMatchCount(ctx context.Context, req *shakesapp.ShakespeareRequest) (*shakesapp.ShakespeareResponse, error) {
        resp := &shakesapp.ShakespeareResponse{}
        texts, err := readFiles(ctx, bucketName, bucketPrefix)
        if err != nil {
                return resp, fmt.Errorf("fails to read files: %s", err)
        }
        for _, text := range texts {
                for _, line := range strings.Split(text, "\n") {
                        line, query := strings.ToLower(line), strings.ToLower(req.Query)
                        isMatch, err := regexp.MatchString(query, line)
                        if err != nil {
                                return resp, err
                        }
                        if isMatch {
                                resp.MatchCount++
                        }
                }
        }
        return resp, nil
}

هذا هو المكان الذي يُطلق فيه اسم regexp.MatchString. من خلال قراءة رمز المصدر، قد تلاحظ أن الدالة يتم استدعاءها داخل الدالة for-loop المتداخلة. لذلك قد يكون استخدام هذه الدالة غير صحيح. لنبحث عن GoDoc لـ regexp.

80b8a4ba1931ff7b.png

ووفقًا للمستند، تجمع regexp.MatchString نمط التعبير العادي في كل استدعاء. إذًا، يبدو أن سبب الاستهلاك الضخم للموارد هو السبب في ذلك.

ملخّص

في هذه الخطوة، افترضت سبب استهلاك الموارد من خلال تحليل الرسم البياني للهب.

التالي

في الخطوة التالية، ستقوم بتحديث رمز المصدر لخدمة الخادم وتأكيد التغيير من الإصدار 1.0.0.

6- تعديل رمز المصدر وتسليط الضوء على الرسومات البيانية الخاصة بالأشكال المختلفة

تعديل رمز المصدر

في الخطوة السابقة، افترضت أنّ استخدام regexp.MatchString له علاقة بالاستهلاك الكبير للموارد. لذلك دعنا نحل هذه المشكلة. افتح الرمز وغيّر هذا الجزء قليلاً.

step4/src/server/main.go

func (s *serverService) GetMatchCount(ctx context.Context, req *shakesapp.ShakespeareRequest) (*shakesapp.ShakespeareResponse, error) {
        resp := &shakesapp.ShakespeareResponse{}
        texts, err := readFiles(ctx, bucketName, bucketPrefix)
        if err != nil {
                return resp, fmt.Errorf("fails to read files: %s", err)
        }

        // step6. considered the process carefully and naively tuned up by extracting
        // regexp pattern compile process out of for loop.
        query := strings.ToLower(req.Query)
        re := regexp.MustCompile(query)
        for _, text := range texts {
                for _, line := range strings.Split(text, "\n") {
                        line = strings.ToLower(line)
                        isMatch := re.MatchString(line)
                        // step6. done replacing regexp with strings
                        if isMatch {
                                resp.MatchCount++
                        }
                }
        }
        return resp, nil
}

كما ترى، يتم الآن استخراج عملية تجميع نمط التعبير العادي من regexp.MatchString ويتم نقلها من حلقة التكرار for المتداخلة.

قبل نشر هذا الرمز، تأكَّد من تعديل سلسلة الإصدار في دالة initProfiler().

step4/src/server/main.go

func initProfiler() {
        cfg := profiler.Config{
                Service:              "server",
                ServiceVersion:       "1.1.0", // step6. update version
                NoHeapProfiling:      true,
                NoAllocProfiling:     true,
                NoGoroutineProfiling: true,
                NoCPUProfiling:       false,
        }
        if err := profiler.Start(cfg); err != nil {
                log.Fatalf("failed to launch profiler agent: %v", err)
        }
}

الآن لنرى كيف يعمل. انشر المجموعة باستخدام الأمر skaffold.

skaffold dev

وبعد فترة، يمكنك إعادة تحميل لوحة بيانات Cloud Profiler ومعرفة كيف يبدو الأمر.

283cfcd4c13716ad.png

احرص على تغيير الإصدار إلى "1.1.0" لتظهر فقط الملفات الشخصية من الإصدار 1.1.0. كما ترى، انخفض طول شريط GetMatchCount ونسبة استخدام وقت وحدة المعالجة المركزية (أي أصبح الشريط أقصر).

e3a1456b4aada9a5.png

ليس فقط من خلال النظر إلى الرسم البياني للشعبية لإصدار واحد، يمكنك أيضًا مقارنة الاختلافات بين نسختين.

841dec77d8ba5595.png

تغيير قيمة المقياس "مقارنة بـ" القائمة المنسدلة إلى "الإصدار" وتغيير قيمة "النسخة المقارنة" إلى "1.0.0"، الإصدار الأصلي.

5553844292d6a537.png

سترى هذا النوع من الرسم البياني للشعلة. شكل الرسم البياني هو نفسه 1.1.0 لكن اللون مختلف. في وضع المقارنة، يعني اللون ما يلي:

  • أزرق: القيمة (استهلاك الموارد) المخفَّضة
  • البرتقالي: القيمة (استهلاك الموارد) المكتسبة
  • الرمادي: محايد

بناءً على وسيلة الإيضاح، لنلقِ نظرة فاحصة على الدالة. من خلال النقر على الشريط الذي تريد تكبيره، يمكنك الاطلاع على المزيد من التفاصيل داخل المكدس. يُرجى النقر على شريط main.(*serverService).GetMatchCount. ومن خلال تمرير مؤشّر الماوس فوق الشريط أيضًا، ستظهر تفاصيل المقارنة.

ca08d942dc1e2502.png

يشير ذلك إلى أنّ الوقت الإجمالي لوحدة المعالجة المركزية (CPU) يتم تقليله من 5.26 ثانية إلى 2.88 ثانية (المجموع 10 ثوانٍ = فترة أخذ العيّنات). هذا تحسُّن كبير.

يمكنك الآن تحسين أداء تطبيقك من خلال تحليل بيانات الملف الشخصي.

ملخّص

في هذه الخطوة، أجريت تعديلاً في خدمة الخادم وأكّدت على التحسين في وضع المقارنة في Cloud Profiler.

التالي

في الخطوة التالية، ستقوم بتحديث رمز المصدر لخدمة الخادم وتأكيد التغيير من الإصدار 1.0.0.

7. خطوة إضافية: تأكيد التحسين في ميزة "تتبُّع العرض الإعلاني بدون انقطاع"

الفرق بين بيانات التتبُّع الموزعة والتحليل المستمر المستمر

في الجزء الأول من الدرس التطبيقي حول الترميز، أكدت أنّه بإمكانك اكتشاف خدمة المؤثِّرة السلبية في الخدمات المصغّرة لمسار الطلب وأنّه لا يمكنك معرفة السبب الدقيق للمشكلة في الخدمة المحدّدة. في هذا الجزء الثاني من الدرس التطبيقي حول الترميز، تعلمت أن التحليل المستمر يتيح لك تحديد المؤثِّرات السلبية داخل الخدمة الواحدة من حِزم الاتصال.

في هذه الخطوة، لنراجع الرسم البياني الانحداري من التتبع الموزع (Cloud Trace) ونرى الفرق من عملية التحليل المستمر.

هذا الرسم البياني الانحداري هو أحد التأثيرات التي تحمل طلب البحث "love". يستغرق ذلك حوالي 6.7 ثانية (6700 ميلي ثانية).

e2b7dec25926ee51.png

وهذا بعد التحسين لنفس الاستعلام. وكما هو موضح، يبلغ إجمالي وقت الاستجابة الآن 1.5 ثانية (1500 ملّي ثانية)، وهذا تحسُّن كبير مقارنةً بعملية التنفيذ السابقة.

feeb7207f36c7e5e.png

من المهم هنا أنّه في الرسم البياني الانحداري للتتبّع الموزَّع، لا تتوفّر معلومات حزمة الاستدعاءات إلّا إذا كانت الأداة تمتد في كل مكان. وتركّز عمليات التتبُّع الموزَّعة أيضًا على وقت الاستجابة على مستوى الخدمات، بينما يركِّز التحليل المستمر على موارد الكمبيوتر (وحدة المعالجة المركزية (CPU) والذاكرة وسلاسل أنظمة التشغيل) لخدمة واحدة.

وفي جانب آخر، يكون التتبّع الموزع هو قاعدة الأحداث، أما الملف الشخصي المستمر فهو إحصائية. لكل عملية تتبُّع رسم بياني مختلف لوقت الاستجابة، وعليك استخدام تنسيق مختلف مثل التوزيع للاطّلاع على مؤشر تغييرات وقت الاستجابة.

ملخّص

في هذه الخطوة، تحقّقت من الفرق بين بيانات التتبُّع الموزعة والتحليل المستمر المستمر.

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

بعد حذف المجموعة، حدِّد "إدارة الهوية وإمكانية الوصول المشرف" > "الإعدادات"، ثم النقر على "إيقاف الصوت" .

45aa37b7d5e1ddd1.png

بعد ذلك، أدخِل رقم تعريف المشروع (وليس اسم المشروع) في النموذج الوارد في مربّع الحوار وأكِّد إيقاف التشغيل.