اطلاعات ردیابی ابزار با استفاده از OpenTelemetry

۱. مقدمه

5af4a7e43b0feaab.png

آخرین به‌روزرسانی: 2021-03-05

قابلیت مشاهده برنامه

مشاهده‌پذیری و OpenTelemetry

قابلیت مشاهده اصطلاحی است که برای توصیف یک ویژگی از یک سیستم به کار می‌رود. سیستمی با قابلیت مشاهده به تیم‌ها اجازه می‌دهد تا به طور فعال سیستم خود را اشکال‌زدایی کنند. در این زمینه، سه رکن قابلیت مشاهده؛ لاگ‌ها، معیارها و ردیابی‌ها، ابزار اساسی برای سیستم جهت دستیابی به قابلیت مشاهده هستند.

OpenTelemetry مجموعه‌ای از مشخصات و SDKها است که ابزارسازی و خروجی گرفتن از داده‌های تله‌متری (لاگ‌ها، معیارها و ردیابی‌ها) مورد نیاز برای مشاهده‌پذیری را تسریع می‌کند. OpenTelemetry یک پروژه استاندارد باز و مبتنی بر جامعه تحت CNCF است. با استفاده از کتابخانه‌هایی که پروژه و اکوسیستم آن ارائه می‌دهند، توسعه‌دهندگان می‌توانند برنامه‌های خود را به روشی بی‌طرف از فروشنده و در برابر معماری‌های متعدد، ابزارسازی کنند.

ردیابی توزیع‌شده

در میان لاگ‌ها، معیارها و ردگیری‌ها، ردگیری، تله‌متری است که میزان تأخیر بخش خاصی از فرآیند در سیستم را نشان می‌دهد. به خصوص در عصر میکروسرویس‌ها، ردگیری توزیع‌شده، محرک قوی برای یافتن گلوگاه‌های تأخیر در کل سیستم توزیع‌شده است.

هنگام تجزیه و تحلیل ردیابی‌های توزیع‌شده، تجسم داده‌های ردیابی کلید درک کلی تأخیرهای سیستم در یک نگاه است. در ردیابی توزیع‌شده، ما مجموعه‌ای از فراخوانی‌ها را برای پردازش یک درخواست واحد به نقطه ورودی سیستم در قالب ردیابی حاوی چندین Span مدیریت می‌کنیم.

Span نشان دهنده یک واحد کاری جداگانه است که در یک سیستم توزیع شده انجام می‌شود و زمان‌های شروع و پایان را ثبت می‌کند. Spanها اغلب روابط سلسله مراتبی بین یکدیگر دارند - در تصویر زیر، همه Spanهای کوچکتر، Spanهای فرزند یک Span بزرگ /messages هستند و در یک Trace جمع شده‌اند که مسیر کار را در یک سیستم نشان می‌دهد.

adbd3ecd69d410c.png

Google Cloud Trace یکی از گزینه‌های موجود برای ردیابی توزیع‌شده در پس‌زمینه است و به خوبی با سایر محصولات Google Cloud یکپارچه شده است.

آنچه خواهید ساخت

در این آزمایشگاه کد، شما قرار است اطلاعات ردیابی ابزار را در سرویس‌هایی به نام "Shakesapp" که روی یک کلاستر Kubernetes که روی موتور Kubernetes گوگل اجرا می‌شود، اجرا می‌شود، ردیابی کنید. معماری Shakesapp به شرح زیر است:

68873c018a7be7de.png

  • کلاینت‌ها یک رشته پرس‌وجو (query string) به سرور ارسال می‌کنند.
  • سرور، کوئری را از کلاینت می‌پذیرد، تمام آثار Shakespare را در قالب متن از Google Cloud Storage دریافت می‌کند، خطوطی را که شامل کوئری هستند جستجو می‌کند و شماره خطی را که با کوئری مطابقت دارد به کلاینت برمی‌گرداند.

شما اطلاعات ردیابی را در طول درخواست، ابزار دقیق خواهید کرد.

آنچه یاد خواهید گرفت

  • نحوه شروع کار با کتابخانه‌های OpenTelemetry Trace در پروژه پایتون
  • نحوه ایجاد دهانه با کتابخانه
  • نحوه انتشار span contextها در سراسر سیم بین اجزای برنامه
  • نحوه ارسال داده‌های ردیابی به Google Cloud Trace
  • نحوه تجزیه و تحلیل ردیابی در Google Cloud Trace

این آزمایشگاه کد توضیح می‌دهد که چگونه میکروسرویس‌های خود را ابزاربندی کنید. برای درک آسان، این مثال فقط شامل ۳ جزء (مولد بار، کلاینت و سرور) است، اما می‌توانید همان فرآیند توضیح داده شده در این آزمایشگاه کد را برای سیستم‌های پیچیده‌تر و بزرگتر اعمال کنید.

آنچه نیاز دارید

  • آشنایی با پایتون ۳

۲. تنظیمات و الزامات

تنظیم محیط خودتنظیم

اگر از قبل حساب گوگل (جیمیل یا برنامه‌های گوگل) ندارید، باید یکی ایجاد کنید . وارد کنسول پلتفرم ابری گوگل ( console.cloud.google.com ) شوید و یک پروژه جدید ایجاد کنید.

اگر از قبل پروژه‌ای دارید، روی منوی کشویی انتخاب پروژه در سمت چپ بالای کنسول کلیک کنید:

۱۵b8b6ac4d917005.png

و در پنجره‌ی باز شده روی دکمه‌ی «پروژه‌ی جدید» کلیک کنید تا یک پروژه‌ی جدید ایجاد شود:

7136b3ee36ebaf89.png

اگر از قبل پروژه‌ای ندارید، باید پنجره‌ای مانند این را برای ایجاد اولین پروژه خود ببینید:

90977ce514204b51.png

پنجره‌ی بعدیِ ایجاد پروژه به شما امکان می‌دهد جزئیات پروژه‌ی جدید خود را وارد کنید:

6d9573e346e930b4.png

شناسه پروژه را به خاطر بسپارید، که یک نام منحصر به فرد در تمام پروژه‌های Google Cloud است (نام بالا قبلاً گرفته شده و برای شما کار نخواهد کرد، متاسفیم!). بعداً در این آزمایشگاه کد به آن PROJECT_ID گفته خواهد شد.

در مرحله بعد، اگر قبلاً این کار را نکرده‌اید، برای استفاده از منابع Google Cloud و فعال کردن Cloud Trace API ، باید صورتحساب را در کنسول توسعه‌دهندگان فعال کنید .

eb5325f65619ad6a.png

اجرای این آزمایشگاه کد نباید بیش از چند دلار برای شما هزینه داشته باشد، اما اگر تصمیم به استفاده از منابع بیشتر بگیرید یا اگر آنها را در حال اجرا رها کنید (به بخش "پاکسازی" در انتهای این سند مراجعه کنید)، می‌تواند بیشتر هزینه داشته باشد. قیمت‌های Google Cloud Trace، Google Kubernetes Engine و Google Artifacat Registry در اسناد رسمی ذکر شده است.

کاربران جدید پلتفرم ابری گوگل واجد شرایط دریافت یک دوره آزمایشی رایگان ۳۰۰ دلاری هستند که این کدلب را کاملاً رایگان می‌کند.

راه‌اندازی پوسته ابری گوگل

اگرچه می‌توان از راه دور و از طریق لپ‌تاپ، Google Cloud و Google Cloud Trace را مدیریت کرد، اما در این آزمایشگاه کد، از Google Cloud Shell ، یک محیط خط فرمان که در فضای ابری اجرا می‌شود، استفاده خواهیم کرد.

این ماشین مجازی مبتنی بر دبیان، تمام ابزارهای توسعه مورد نیاز شما را در خود جای داده است. این ماشین مجازی یک دایرکتوری خانگی ۵ گیگابایتی دائمی ارائه می‌دهد و در فضای ابری گوگل اجرا می‌شود که عملکرد شبکه و احراز هویت را تا حد زیادی بهبود می‌بخشد. این بدان معناست که تنها چیزی که برای این آزمایشگاه کد نیاز دارید یک مرورگر است (بله، روی کروم‌بوک هم کار می‌کند).

برای فعال کردن Cloud Shell از کنسول Cloud، کافیست روی Activate Cloud Shell کلیک کنید. gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A (فقط چند لحظه طول می‌کشد تا آماده شود و به محیط متصل شود).

ff81d016724c4f67.png

fbe156ee6edfbb2e.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 جستجو کنید:

a3e716fc9e7454e9.png

Cloud Shell همچنین برخی از متغیرهای محیطی را به طور پیش‌فرض تنظیم می‌کند که ممکن است هنگام اجرای دستورات بعدی مفید باشند.

echo $GOOGLE_CLOUD_PROJECT

خروجی کامند

<PROJECT_ID>

در نهایت، منطقه پیش‌فرض و پیکربندی پروژه را تنظیم کنید.

gcloud config set compute/zone us-central1-f

شما می‌توانید مناطق مختلفی را انتخاب کنید. برای اطلاعات بیشتر، به بخش مناطق و نواحی مراجعه کنید.

تنظیمات پایتون

در این آزمایشگاه کد، ما از "poetry" برای مدیریت دقیق نسخه‌های بسته استفاده می‌کنیم. دستور زیر را روی Cloud Shell اجرا کنید:

curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 -
source $HOME/.poetry/env

راه‌اندازی یک کلاستر گوگل کوبرنتیز

در این آزمایشگاه کد، شما یک کلاستر از میکروسرویس‌ها را روی موتور کوبرنتیز گوگل (GKE) اجرا خواهید کرد. فرآیند این آزمایشگاه کد به شرح زیر است:

  1. پروژه پایه را در Cloud Shell دانلود کنید
  2. ساخت میکروسرویس‌ها در کانتینرها
  3. کانتینرها را در فهرست آثار باستانی گوگل (GAR) بارگذاری کنید
  4. کانتینرها را روی GKE مستقر کنید
  5. کد منبع سرویس‌ها را برای ابزار دقیق ردیابی تغییر دهید
  6. به مرحله ۲ بروید

فعال کردن موتور Kubernetes

ابتدا، ما یک کلاستر Kubernetes راه‌اندازی می‌کنیم که Shakesapp روی GKE اجرا می‌شود، بنابراین باید GKE را فعال کنیم. به منوی "Kubernetes Engine" بروید و دکمه ENABLE را فشار دهید.

56c680e93e169731.png

اکنون آماده ایجاد یک خوشه Kubernetes هستید.

ایجاد خوشه Kubernetes

در Cloud Shell، دستور زیر را برای ایجاد یک کلاستر Kubernetes اجرا کنید. لطفاً تأیید کنید که مقدار منطقه، زیر منطقه‌ای است که برای ایجاد مخزن Artifact Registry استفاده کرده‌اید. اگر منطقه مخزن شما منطقه را پوشش نمی‌دهد، مقدار منطقه را us-central1-f تغییر دهید.

gcloud container clusters create otel-trace-codelab --zone us-central1-f \
--num-nodes 1 \
--machine-type e2-highcpu-4

خروجی دستور

Creating cluster otel-trace-codelab in us-central1-f... Cluster is being health-checked (master is healthy)...done.
Created [https://container.googleapis.com/v1/projects/psychic-order-307806/zones/us-central1-f/clusters/otel-trace-codelab].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-f/otel-trace-codelab?project=psychic-order-307806
kubeconfig entry generated for otel-trace-codelab.
NAME                LOCATION       MASTER_VERSION    MASTER_IP        MACHINE_TYPE  NODE_VERSION      NUM_NODES  STATUS
otel-trace-codelab  us-central1-f  1.18.12-gke.1210  104.154.162.176  e2-medium     1.18.12-gke.1210  3          RUNNING

ثبت آثار باستانی و تنظیم اسکلت

حالا ما یک کلاستر Kubernetes آماده برای استقرار داریم. در مرحله بعد، ما یک رجیستری کانتینر برای ارسال و استقرار کانتینرها آماده می‌کنیم. برای این مرحله، باید GAR و skaffold را برای استفاده از آن تنظیم کنیم.

تنظیم رجیستری مصنوعات

به منوی «ثبت آثار باستانی» بروید و دکمه‌ی «فعال‌سازی» (ENABLE) را فشار دهید.

f7493243bae0cdf7.png

بعد از چند لحظه، مرورگر مخزن GAR را مشاهده خواهید کرد. روی دکمه "ایجاد مخزن" کلیک کنید و نام مخزن را وارد کنید.

f97f337f5476651.png

در این codelab، من مخزن جدید را trace-codelab نامگذاری می‌کنم. قالب artifact "Docker" و نوع مکان "Region" است. منطقه‌ای نزدیک به منطقه‌ای که برای منطقه پیش‌فرض Google Compute Engine تعیین کرده‌اید را انتخاب کنید. برای مثال، در این مثال "us-central1-f" در بالا انتخاب شد، بنابراین در اینجا "us-central1 (Iowa)" را انتخاب می‌کنیم. سپس روی دکمه "CREATE" کلیک کنید.

2f04143077ca56db.png

حالا عبارت "trace-codelab" را در مرورگر مخزن مشاهده می‌کنید.

7a3c1f47346bea15.png

بعداً برای بررسی مسیر رجیستری به اینجا برمی‌گردیم.

نصب اسکفولد

Skaffold ابزاری مفید برای زمانی است که روی ساخت میکروسرویس‌ها روی Kubernetes کار می‌کنید. این ابزار گردش کار ساخت، ارسال و استقرار کانتینرهای برنامه‌ها را با مجموعه‌ای از دستورات کوچک مدیریت می‌کند. Skaffold به طور پیش‌فرض از رجیستری Docker به عنوان رجیستری کانتینر استفاده می‌کند، بنابراین باید Skaffold را طوری پیکربندی کنید که GAR را هنگام ارسال کانتینرها به آن تشخیص دهد.

دوباره Cloud Shell را باز کنید و تأیید کنید که آیا skaffold نصب شده است یا خیر. (Cloud Shell به طور پیش‌فرض skaffold را در محیط نصب می‌کند.) دستور زیر را اجرا کنید و نسخه skaffold را مشاهده کنید.

skaffold version

خروجی دستور

v1.20.0

اکنون می‌توانید مخزن پیش‌فرض را برای استفاده skaffold ثبت کنید. برای به دست آوردن مسیر رجیستری، به داشبورد Artifact Registry بروید و روی نام مخزنی که در مرحله قبل تنظیم کرده‌اید کلیک کنید.

55173fe922f40327.png

سپس مسیرهای breadcrumbs را در بالای صفحه مشاهده خواهید کرد. کلیک کنید e157b1359c3edc06.png آیکون برای کپی کردن مسیر رجیستری به کلیپ بورد.

a9b0fa44c37e0178.png

با کلیک بر روی دکمه کپی، کادر محاوره‌ای در پایین مرورگر با پیامی مانند زیر مشاهده خواهید کرد:

«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

همچنین، باید رجیستری را با پیکربندی داکر پیکربندی کنید. دستور زیر را اجرا کنید:

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 راه‌اندازی کنید.

خلاصه

در این مرحله، محیط codelab خود را تنظیم می‌کنید:

  • راه‌اندازی پوسته ابری
  • یک مخزن Artifact Registy برای رجیستری کانتینر ایجاد کرد.
  • تنظیم skaffold برای استفاده از رجیستری کانتینر
  • یک کلاستر Kubernetes ایجاد کردیم که میکروسرویس‌های codelab در آن اجرا می‌شوند.

بعدی

در مرحله بعد، شما میکروسرویس‌های خود را ساخته، به کلاستر اضافه و مستقر خواهید کرد.

۳. ساخت، اجرا و استقرار میکروسرویس‌ها

دانلود مطالب codelab

در مرحله قبل، تمام پیش‌نیازهای این codelab را تنظیم کردیم. اکنون آماده‌اید تا کل میکروسرویس‌ها را روی آنها اجرا کنید. مطالب codelab در GitHub میزبانی می‌شود، بنابراین آنها را با دستور git زیر در محیط Cloud Shell دانلود کنید.

cd ~
git clone https://github.com/GoogleCloudPlatform/opentelemetry-trace-codelab-python.git

ساختار دایرکتوری پروژه به صورت زیر است:

shakesapp-python
├── LICENSE
├── manifests
│   ├── client.yaml
│   ├── loadgen.yaml
│   └── server.yaml
├── proto
│   └── shakesapp.proto
├── skaffold.yaml
└── src
    ├── client
    ├── loadgen
    └── server
  • مانیفست‌ها: فایل‌های مانیفست Kubernetes
  • proto: تعریف proto برای ارتباط بین کلاینت و سرور
  • src: دایرکتوری‌های مربوط به کد منبع هر سرویس
  • skaffold.yaml: فایل پیکربندی برای skaffold

دستور skaffold را اجرا کنید

در نهایت، شما آماده‌اید تا کل محتوا را روی کلاستر Kubernetes که ایجاد کرده‌اید، بسازید، بارگذاری کنید و مستقر کنید. این کار به نظر می‌رسد شامل چندین مرحله باشد، اما در واقع skaffold همه چیز را برای شما انجام می‌دهد. بیایید این کار را با دستور زیر امتحان کنیم:

cd shakesapp-python
skaffold run --tail

به محض اجرای دستور، خروجی لاگ 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

هشدار : اگر با خطایی مانند "بدون دسترسی به مخزن تصویر مشخص شده" مواجه شدید، بررسی کنید که آیا دستور skaffold صرف نظر از پیکربندی شما روی مخزن پیش‌فرض در skaffold، سعی در ارسال تصاویر به Docker Hub (docker.io) دارد یا خیر. در این صورت، مانند زیر، گزینه "–default-repo" را به "skaffold run" اضافه کنید.

دستور skaffold run –tail –default-repo=us-central1-docker.pkg.dev/[project ID]/[repository name] را اجرا کنید.

پس از استقرار، گزارش‌های واقعی برنامه را که به stdout در هر کانتینر ارسال می‌شوند، مانند این خواهید دید:

خروجی دستور

[server] {"event": "starting server: 0.0.0.0:5050", "severity": "info", "timestamp": "2021-03-17T05:25:56.758575Z"}
[client] [2021-03-17 05:25:54 +0000] [1] [INFO] Starting gunicorn 20.0.4
[client] [2021-03-17 05:25:54 +0000] [1] [INFO] Listening at: http://0.0.0.0:8080 (1)
[client] [2021-03-17 05:25:54 +0000] [1] [INFO] Using worker: threads
[client] [2021-03-17 05:25:54 +0000] [7] [INFO] Booting worker with pid: 7
[client] {"event": "server address is serverservice:5050", "severity": "info", "timestamp": "2021-03-17T05:25:54.888627Z"}
[client] {"event": "request to server with query: world", "severity": "info", "timestamp": "2021-03-17T05:26:11.550923Z"}
[server] {"event": "query: world", "severity": "info", "timestamp": "2021-03-17T05:26:11.567048Z"}
[loadgen] {"event": "check connectivity: http://clientservice:8080/_healthz", "severity": "info", "timestamp": "2021-03-17T05:26:11.533605Z"}
[loadgen] {"event": "/_healthz response: ok", "severity": "info", "timestamp": "2021-03-17T05:26:11.544267Z"}
[loadgen] {"event": "confirmed connection ot clientservice", "severity": "info", "timestamp": "2021-03-17T05:26:11.544527Z"}

در نهایت، شما آماده هستید تا برنامه خود را با OpenTelemetry برای ردیابی توزیع‌شده سرویس‌ها، تجهیز کنید.

خلاصه

در این مرحله، شما مواد codelab را در محیط خود آماده کرده‌اید و تأیید کرده‌اید که skaffold مطابق انتظار اجرا می‌شود.

بعدی

در مرحله بعد، کد منبع سرویس loadgen را برای ابزار دقیق اطلاعات ردیابی تغییر خواهید داد.

۴. ابزار دقیق برای HTTP

مفهوم ابزار دقیق ردیابی و انتشار

قبل از ویرایش کد منبع، اجازه دهید به طور خلاصه نحوه عملکرد ردپاهای توزیع‌شده را در یک نمودار ساده توضیح دهم.

c8c659deaa9c9091.png

در این مثال، ما کد را برای ارسال اطلاعات Trace و Span به Cloud Trace و انتشار زمینه ردیابی در سراسر درخواست از سرویس loadgen به سرویس سرور، تنظیم می‌کنیم.

برنامه باید متادیتای Trace مانند Trace ID و Span ID را ارسال کند تا Cloud Trace تمام spanهایی که Trace ID یکسانی دارند را در یک trace جمع‌آوری کند. همچنین برنامه باید Trace contextها (ترکیبی از Trace ID و Span ID مربوط به span والد) را در هنگام درخواست سرویس‌های پایین‌دستی منتشر کند تا بتواند از Trace context که در حال مدیریت آن است، آگاه باشد.

OpenTelemetry به شما کمک می‌کند:

  • برای تولید Trace ID و Span ID منحصر به فرد
  • برای ارسال Trace ID و Span ID به backend
  • برای انتشار زمینه‌های ردیابی به سایر سرویس‌ها

دهانه اول ابزار

خدمات ژنراتور بار ابزار دقیق

با فشار دادن دکمه، ویرایشگر Cloud Shell را باز کنید 776a11bfb2122549.png در بالا سمت راست Cloud Shell. از پنجره اکسپلورر در پنل سمت چپ، src/loadgen/loadgen.py را باز کنید و تابع main را پیدا کنید.

src/loadgen/loadgen.py

def main():
    ...
    # start request loop to client service
    logger.info("start client request loop")
    addr = f"http://{target}"
    while True:
        logger.info("start request to client")
        call_client(addr)
        logger.info("end request to client")
        time.sleep(2.0)

در تابع main ، حلقه‌ای را می‌بینید که تابع call_client را فراخوانی می‌کند. در پیاده‌سازی فعلی، سکتورین دارای ۲ خط لاگ است که شروع و پایان فراخوانی تابع را ثبت می‌کنند. حال بیایید اطلاعات Span را برای ردیابی تأخیر فراخوانی تابع، ابزاربندی کنیم.

ابتدا، باید یک Span با یک Trace ID و Span ID منحصر به فرد ایجاد کنید. OpenTelemetry کتابخانه مفیدی برای آن فراهم می‌کند. خطوط زیر را برای وارد کردن کتابخانه‌های OpenTelemetry به کد خود اضافه کنید.

 import structlog
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.instrumentation.requests import RequestsInstrumentor
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator

از آنجا که مولد بار، برنامه کلاینت را در HTTP از طریق ماژول requests فراخوانی می‌کند، ما از بسته افزونه برای requests استفاده می‌کنیم و ابزار دقیق را فعال می‌کنیم.

 from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
+
+RequestsInstrumentor().instrument()

سپس نمونه Tracer را تنظیم کنید که تنظیمات Trace Contenxt و export را مدیریت کند.

     target = os.environ.get("CLIENT_ADDR", "0.0.0.0:8080")

+    exporter = CloudTraceSpanExporter()
+    trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))
+    tracer = trace.get_tracer(__name__)
+    propagate.set_global_textmap(CloudTraceFormatPropagator())
+    trace.set_tracer_provider(TracerProvider())
+
     # connectivity check to client service
     healthz = f"http://{target}/_healthz"
     logger.info(f"check connectivity: {healthz}")

توجه داشته باشید که از آنجایی که این یک آزمایشگاه کد برای درک نحوه‌ی عملکرد ابزار ردیابی است، ما Tracer را طوری پیکربندی می‌کنیم که تک تک درخواست‌ها را ثبت کرده و آنها را به backend ارسال کند. ( SimpleSpanProcessor() ) این برای محیط‌های عملیاتی مناسب نیست، بنابراین هنگام ابزاربندی برنامه‌ی عملیاتی خود، حتماً این قسمت را تغییر دهید.

حالا می‌توانید با استفاده از Tracer، Spanها را ابزاربندی کنید. نکته اینجاست که کاری که باید انجام دهید این است که یک Span را به صورت صریح تولید کنید، و تمام! اگرچه دو خط وجود دارد که ابرداده رویداد را به Span اضافه می‌کنند، اما نیازی نیست Trace ID و Span ID منحصر به فرد را به صورت دستی تولید کرده و آنها را در Span جاسازی کنید.

     logger.info("start client request loop")
     addr = f"http://{target}"
     while True:
-        logger.info("start request to client")
-        call_client(addr)
-        logger.info("end request to client")
+        with tracer.start_as_current_span("loadgen") as root_span:
+            root_span.add_event(name="request_start")
+            logger.info("start request to client")
+            call_client(addr)
+            root_span.add_event(name="request_end")
+            logger.info("end request to client")
         time.sleep(2.0)

برای اینکه Docker build بتواند بسته‌های مورد نیاز OpenTelemetry را دریافت کند، دستور زیر را اجرا کنید:

poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0"
poetry add "opentelemetry-propagator-gcp=^1.0.0rc0"
poetry add "opentelemetry-instrumentation-requests=^0.20b0"

می‌توانید تأیید کنید که توضیحات وابستگی مربوطه در pyproject.toml نوشته شده است.

خدمات مشتری ابزار دقیق

در بخش قبل، بخشی که در مستطیل قرمز رنگ در شکل زیر مشخص شده است را instrumentation کردیم. ما اطلاعات span را در سرویس load generator instrumentation کردیم. مشابه سرویس load generator، اکنون باید سرویس client را instrumentation کنیم. تفاوت آن با سرویس load generator این است که سرویس client باید اطلاعات Trace ID منتشر شده از سرویس load generator در هدر HTTP را استخراج کرده و از ID برای تولید Spans استفاده کند.

ae074d4513c9931f.png

ویرایشگر Cloud Shell را باز کنید و ماژول‌های مورد نیاز را مانند کاری که برای سرویس مولد بار انجام دادیم، اضافه کنید.

src/client/client.py

 import flask
 import grpc
 import structlog
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.instrumentation.flask import FlaskInstrumentor
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import \
+    CloudTraceFormatPropagator

 import shakesapp_pb2
 import shakesapp_pb2_grpc

متوجه شدید که FlaskInstrumentor وارد کرده‌اید که ابزار دقیق خودکار را برای برنامه Flask از طرف کاربران فعال می‌کند تا هدرهای HTTP را برای به دست آوردن Trace Contexts با یک خط کد استخراج کند. انجمن OpenTelemetry ادغام‌های مفید مشابهی را با سایر کتابخانه‌های اصلی ارائه می‌دهد. برای اطلاعات بیشتر، می‌توانید به مستندات رسمی مراجعه کنید.

 app = flask.Flask(__name__)
+FlaskInstrumentor().instrument_app(app)

قبل از شروع ابزار دقیق، دوباره باید نمونه Tracer را مشابه کاری که در سرویس مولد بار انجام دادیم، آماده کنید.

 logger.info(f"server address is {SERVER_ADDR}")

+exporter = CloudTraceSpanExporter()
+trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))
+propagate.set_global_textmap(CloudTraceFormatPropagator())
+trace.set_tracer_provider(TracerProvider())

 @app.route("/")
 def main_handler():
    ....

حالا آماده‌ی اضافه کردن ابزار دقیق به هندلر هستیم. main_handler() را پیدا کنید و بخشی که درخواست gRPC را به سرویس سرور ارسال می‌کند را تغییر دهید.

@app.route("/")
def main_handler():
    q, count = random.choice(list(queries.items()))

    # get Tracer
    tracer = trace.get_tracer(__name__)

    with tracer.start_as_current_span("client") as cur_span:
        channel = grpc.insecure_channel(SERVER_ADDR)
        stub = shakesapp_pb2_grpc.ShakespeareServiceStub(channel)
        logger.info(f"request to server with query: {q}")
        cur_span.add_event("server_call_start")
        resp = stub.GetMatchCount(shakesapp_pb2.ShakespeareRequest(query=q))
        cur_span.add_event("server_call_end")
        if count != resp.match_count:
            raise UnexpectedResultError(
                f"The expected count for '{q}' was {count}, but result was {resp.match_count } obtained"
            )
        result = str(resp.match_count)
        logger.info(f"matched count for '{q}' is {result}")
    return result

به طور مشابه برای بارگذاری سرویس generator، بسته‌های مورد نیاز را با دستور زیر به pyproject.toml اضافه کنید.

poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0"
poetry add "opentelemetry-propagator-gcp=^1.0.0rc0"
poetry add "opentelemetry-instrumentation-flask=^0.20b0"

سپس سعی کنید برنامه را با دستور skaffold run اجرا کنید و ببینید داشبورد Cloud Trace چه چیزی را نشان می‌دهد:

skaffold run --tail

پس از مشاهده‌ی برخی پیام‌های ساخت، ارسال و استقرار، گزارش‌های برنامه را در قالب JSON مشاهده خواهید کرد. برای بررسی اینکه آیا اطلاعات ردیابی را دریافت می‌کنید، به Cloud Trace > Trace list بروید. از آنجا که سرویس تولیدکننده‌ی بار، درخواست‌ها را به صورت دوره‌ای به سرویس کلاینت ارسال می‌کند و شما ردیابی‌ها را برای همه درخواست‌ها فعال کرده‌اید، شروع به مشاهده‌ی نقاط زیادی در لیست ردیابی می‌کنید.

f7440360551980e.png

با کلیک روی یکی از آنها، یک نمودار آبشاری مانند زیر مشاهده خواهید کرد که میزان تأخیر هر بخش از فرآیند درخواست و پاسخ را توضیح می‌دهد. کادر کنار "نمایش رویدادها" را پیدا کنید، سپس حاشیه‌نویسی‌ها را درون نمودار آبشاری مشاهده خواهید کرد. این حاشیه‌نویسی‌ها، همان‌هایی هستند که شما با استفاده از متد span.add_event() در کد ایجاد کرده‌اید.

67596a4a313738.png

ممکن است متوجه شوید که spanها را از سرویس سرور نمی‌بینید. این درست است زیرا ما اصلاً spanها را در سرویس سرور تنظیم نکرده‌ایم.

خلاصه

در این مرحله، شما سرویس تولیدکننده بار و سرویس کلاینت را ابزار دقیق کرده‌اید و تأیید کرده‌اید که می‌توانید با موفقیت Trace Context را در بین سرویس‌ها منتشر کنید و اطلاعات Span را از هر دو سرویس به Cloud Trace صادر کنید.

بعدی

در مرحله بعد، شما سرویس کلاینت و سرویس سرور را برای تأیید نحوه انتشار Trace Context از طریق gRPC، ابزاربندی خواهید کرد.

۵. ابزار دقیق برای gRPC

در مرحله قبل، نیمه اول درخواست را در این میکروسرویس‌ها به صورت ابزاری پیاده‌سازی کردیم. در این مرحله، سعی می‌کنیم ارتباط gRPC بین سرویس کلاینت و سرویس سرور را به صورت ابزاری پیاده‌سازی کنیم. (مستطیل سبز و بنفش در تصویر زیر)

c4dec3e741c3ab4f.png

ابزار دقیق خودکار برای کلاینت gRPC

اکوسیستم OpenTelemetry کتابخانه‌های مفید زیادی را ارائه می‌دهد که به توسعه‌دهندگان در ابزارسازی برنامه‌ها کمک می‌کند. در مرحله قبل، ما از ابزارسازی خودکار برای ماژول "requests" استفاده کردیم. در این مرحله، از آنجایی که سعی داریم Trace Context را از طریق gRPC منتشر کنیم، از کتابخانه برای آن استفاده می‌کنیم.

src/client/client.py

 import flask
 import grpc
 import structlog
 from opentelemetry import propagate, trace
 from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
 from opentelemetry.instrumentation.flask import FlaskInstrumentor
+from opentelemetry.instrumentation.grpc import GrpcInstrumentorClient
 from opentelemetry.sdk.trace import TracerProvider
 from opentelemetry.sdk.trace.export import SimpleSpanProcessor
 from opentelemetry.propagators.cloud_trace_propagator import \
     CloudTraceFormatPropagator
 import shakesapp_pb2
 import shakesapp_pb2_grpc


 app = flask.Flask(__name__)
 FlaskInstrumentor().instrument_app(app)
+GrpcInstrumentorClient().instrument()

برای سرویس کلاینت، کاری که باید برای ابزار دقیق انجام دهیم بسیار کوچک است. کاری که می‌خواهیم انجام دهیم این است که Trace Context را منتشر کنیم، که ترکیبی از Trace ID و Span ID مربوط به Span فعلی از طریق gRPC است. بنابراین ما GrpcInstrumentatorClient.instrument() را فراخوانی می‌کنیم تا کلاینت gRPC در تابع hander بتواند Trace Context را در هدر HTTP زیرین جاسازی کند.

مطمئن شوید که وابستگی‌های جدید را با دستور poetry add به pyproject.toml اضافه می‌کنید:

poetry add "opentelemetry-instrumentation-grpc=^0.20b0"

ابزار دقیق خودکار برای سرور gRPC

مانند کاری که برای کلاینت gRPC انجام دادیم، برای سرور gRPC نیز تابع automatic instrumentation را فراخوانی می‌کنیم. کدهای زیر را به فایل اضافه کنید و در بالای فایل، تابع GrpcInstrumentationServer().instrument() را فراخوانی کنید.

هشدار : حتماً تماس بگیرید

GrpcInstrumentationServe() 

در این مرحله، نه

GrpcInstrumentationClient()

.

src/server/server.py

 import grpc
 import structlog
 from google.cloud import storage
 from grpc_health.v1 import health_pb2, health_pb2_grpc
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator

 import shakesapp_pb2
 import shakesapp_pb2_grpc


 BUCKET_NAME = "dataflow-samples"
 BUCKET_PREFIX = "shakespeare/"

+# enable auto gRPC server trace instrumentation
+GrpcInstrumentorServer().instrument()
+

و در مرحله بعد، صادرکننده را برای ارسال اطلاعات ردیابی به بک‌اند Cloud Trace اضافه خواهید کرد. کد زیر را در تابع serve() اضافه کنید.

def serve():
+    # start trace exporter
+    trace.set_tracer_provider(TracerProvider())
+    trace.get_tracer_provider().add_span_processor(
+        SimpleSpanProcessor(CloudTraceSpanExporter())
+    )
+    propagators.set_global_textmap(CloudTraceFormatPropagator())
+
+    # add gRPC services to server
     server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
     service = ShakesappService()
     shakesapp_pb2_grpc.add_ShakespeareServiceServicer_to_server(service, server)
     health_pb2_grpc.add_HealthServicer_to_server(service, server)

مطمئن شوید که بسته‌های تازه اضافه شده را در سرویس سرور اضافه می‌کنید.

poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0"
poetry add "opentelemetry-instrumentation-grpc=^0.20b0"
poetry add "opentelemetry-propagator-gcp=^1.0.0rc0"
poetry add "opentelemetry-instrumentation=^0.20b0"

میکروسرویس را اجرا کنید و ردیابی را تأیید کنید

سپس کد اصلاح‌شده خود را با دستور skaffold اجرا کنید.

skaffold run --tail

حالا دوباره، تعدادی ردپا در صفحه فهرست ردپای Cloud Trace می‌بینید. روی یکی از ردپاها کلیک کنید و می‌بینید که این ردپاها از سرویس تولیدکننده بار تا سرویس سرور را در بر می‌گیرند.

۱۴۱cb620245b689d.png

خلاصه

در این مرحله، شما ارتباطات مبتنی بر gRPC را با پشتیبانی کتابخانه‌های اکوسیستم OpenTelemetry تجهیز کردید. همچنین، تأیید کردید که Trace Context تولید شده در سرویس تولیدکننده بار با موفقیت به سرویس سرور تحویل داده شده است.

۶. تبریک

شما با موفقیت ردیابی‌های توزیع‌شده را با OpenTelemery ایجاد کردید و تأخیر درخواست‌ها را در سراسر میکروسرویس در Google Cloud Trace تأیید کردید.

برای تمرین‌های طولانی‌تر، می‌توانید خودتان موضوعات زیر را امتحان کنید.

  • پیاده‌سازی فعلی تمام span های تولید شده توسط بررسی سلامت را ارسال می‌کند. چگونه می‌توانید این span ها را از Cloud Traces فیلتر کنید؟ راهنمایی اینجا است.
  • گزارش‌های رویداد را با spanها مرتبط کنید و ببینید که چگونه در Google Cloud Trace و Google Cloud Logging کار می‌کند. راهنمایی اینجا است.
  • برخی از سرویس‌ها را با سرویسی به زبان دیگر جایگزین کنید و سعی کنید آن را با OpenTelemetry برای آن زبان ابزاربندی کنید.

هشدار : موتور کوبرنتیز گوگل و رجیستری مصنوعات گوگل دائماً منابع را مصرف می‌کنند.

تمیز کردن

پس از این آزمایش کد، لطفاً خوشه Kubernetes را متوقف کنید و حتماً پروژه را حذف کنید تا هزینه‌های غیرمنتظره‌ای روی Google Kubernetes Engine، Google Cloud Trace و Google Artifact Registry دریافت نکنید.

ابتدا با دستور زیر کلاستر را حذف کنید:

skaffold delete

خروجی دستور

Cleaning up...
 - deployment.apps "clientservice" deleted
 - service "clientservice" deleted
 - deployment.apps "loadgen" deleted
 - deployment.apps "serverservice" deleted
 - service "serverservice" deleted

پس از حذف کلاستر، از قسمت منو، گزینه "IAM & Admin" > "Settings" را انتخاب کرده و سپس روی دکمه "SHUT DOWN" کلیک کنید.

578ca2b72a161e9d.png

سپس شناسه پروژه (نه نام پروژه) را در فرم موجود در کادر محاوره‌ای وارد کنید و خاموش شدن را تأیید کنید.