1. مقدمه
آخرین به روز رسانی: 2022-07-14
قابلیت مشاهده برنامه
مشاهدهپذیری و نمایهساز پیوسته
مشاهده پذیری اصطلاحی است که برای توصیف یک ویژگی از یک سیستم استفاده می شود. یک سیستم با قابلیت مشاهده به تیم ها اجازه می دهد تا به طور فعال سیستم خود را اشکال زدایی کنند. در آن زمینه، سه رکن مشاهده پذیری; گزارشها، متریکها و ردیابیها ابزار اساسی سیستم برای به دست آوردن قابلیت مشاهده هستند.
همچنین علاوه بر سه رکن مشاهدهپذیری، نمایهسازی پیوسته یکی دیگر از مؤلفههای کلیدی برای مشاهدهپذیری است و پایگاه کاربران را در صنعت گسترش میدهد . Cloud Profiler یکی از مبتکران است و یک رابط کاربری آسان برای بررسی معیارهای عملکرد در پشته های تماس برنامه ارائه می دهد.
این کد لبه قسمت 2 از سری است و ابزار دقیق یک عامل پروفایلر پیوسته را پوشش می دهد. قسمت 1 ردیابی توزیع شده را با OpenTelemetry و Cloud Trace پوشش می دهد و با قسمت 1 درباره شناسایی بهتر گلوگاه میکروسرویس ها بیشتر خواهید آموخت.
چیزی که خواهی ساخت
در این لبه کد، میخواهید عامل پروفایلساز پیوسته را در سرویس سرور «برنامه Shakespeare» (معروف به Shakesapp) که روی خوشه Google Kubernetes Engine اجرا میشود، ابزار کنید. معماری Shakesapp به شرح زیر است:
- Loadgen یک رشته پرس و جو را در HTTP برای مشتری ارسال می کند
- کلاینت ها از طریق پرس و جو از بارگذار به سرور در gRPC عبور می کنند
- سرور درخواست مشتری را میپذیرد، همه آثار Shakespare را در قالب متن از Google Cloud Storage واکشی میکند، خطوطی را که حاوی پرس و جو هستند جستجو میکند و شماره خطی را که مطابقت دارد به مشتری برمیگرداند.
در قسمت 1، متوجه شدید که گلوگاه در جایی در سرویس سرور وجود دارد، اما نتوانستید علت دقیق آن را شناسایی کنید.
چیزی که یاد خواهید گرفت
- نحوه تعبیه عامل پروفایلر
- نحوه بررسی گردن بطری در Cloud Profiler
این کد لبه توضیح میدهد که چگونه یک عامل نمایهساز پیوسته را در برنامه خود ابزارسازی کنید.
آنچه شما نیاز دارید
- دانش اولیه Go
- دانش اولیه Kubernetes
2. راه اندازی و الزامات
تنظیم محیط خود به خود
اگر قبلاً یک حساب Google (Gmail یا Google Apps) ندارید، باید یک حساب ایجاد کنید . به کنسول Google Cloud Platform ( consol.cloud.google.com ) وارد شوید و یک پروژه جدید ایجاد کنید.
اگر قبلاً پروژه ای دارید، روی منوی کشویی انتخاب پروژه در سمت چپ بالای کنسول کلیک کنید:
و روی دکمه "پروژه جدید" در گفتگوی حاصل کلیک کنید تا یک پروژه جدید ایجاد کنید:
اگر قبلاً پروژه ای ندارید، باید یک دیالوگ مانند این را ببینید تا اولین پروژه خود را ایجاد کنید:
گفتگوی بعدی ایجاد پروژه به شما امکان می دهد جزئیات پروژه جدید خود را وارد کنید:
شناسه پروژه را به خاطر بسپارید، که یک نام منحصر به فرد در تمام پروژه های Google Cloud است (نام بالا قبلاً گرفته شده است و برای شما کار نخواهد کرد، متأسفیم!). بعداً در این آزمایشگاه کد به عنوان PROJECT_ID نامیده خواهد شد.
در مرحله بعد، اگر قبلاً این کار را انجام نداده اید، برای استفاده از منابع Google Cloud و فعال کردن Cloud Trace API، باید صورتحساب را در Developers Console فعال کنید .
گذراندن این کد نباید بیش از چند دلار هزینه داشته باشد، اما اگر تصمیم به استفاده از منابع بیشتری داشته باشید یا آنها را در حال اجرا رها کنید، ممکن است بیشتر باشد (به بخش "پاکسازی" در انتهای این سند مراجعه کنید). قیمتهای Google Cloud Trace، Google Kubernetes Engine و Google Artifact Registry در اسناد رسمی ذکر شده است.
- قیمت گذاری مجموعه عملیات Google Cloud | مجموعه عملیات
- قیمت گذاری | مستندات موتور Kubernetes
- قیمت گذاری رجیستری مصنوعات | اسناد ثبت مصنوعات
کاربران جدید Google Cloud Platform واجد شرایط استفاده آزمایشی رایگان 300 دلاری هستند که باید این نرم افزار کد را کاملاً رایگان کند.
Google Cloud Shell Setup
در حالی که Google Cloud و Google Cloud Trace میتوانند از راه دور از لپتاپ شما کار کنند، در این نرمافزار از Google Cloud Shell استفاده میکنیم، یک محیط خط فرمان که در Cloud اجرا میشود.
این ماشین مجازی مبتنی بر دبیان با تمام ابزارهای توسعه که شما نیاز دارید بارگذاری شده است. این دایرکتوری اصلی 5 گیگابایتی دائمی را ارائه می دهد و در Google Cloud اجرا می شود و عملکرد شبکه و احراز هویت را بسیار افزایش می دهد. این بدان معنی است که تمام چیزی که برای این کد لبه نیاز دارید یک مرورگر است (بله، روی کروم بوک کار می کند).
برای فعال کردن Cloud Shell از Cloud Console، کافی است روی Activate 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 (GKE) اجرا خواهید کرد. فرآیند این کد لبه به شرح زیر است:
- پروژه پایه را در Cloud Shell دانلود کنید
- میکروسرویس ها را در ظروف بسازید
- بارگذاری کانتینرها در Google Artifact Registry (GAR)
- کانتینرها را روی GKE مستقر کنید
- کد منبع خدمات را برای ابزار دقیق ردیابی تغییر دهید
- به مرحله 2 بروید
موتور Kubernetes را فعال کنید
ابتدا، ما یک خوشه Kubernetes را راه اندازی می کنیم که در آن Shakesapp روی GKE اجرا می شود، بنابراین باید GKE را فعال کنیم. به منوی "Kubernetes Engine" بروید و دکمه ENABLE را فشار دهید.
اکنون شما آماده ایجاد یک خوشه Kubernetes هستید.
خوشه Kubernetes را ایجاد کنید
در Cloud Shell، دستور زیر را برای ایجاد یک خوشه Kubernetes اجرا کنید. لطفاً تأیید کنید که مقدار منطقه زیر ناحیه ای است که برای ایجاد مخزن رجیستری مصنوع استفاده خواهید کرد. اگر منطقه مخزن شما منطقه را پوشش نمی دهد، مقدار منطقه 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
رجیستری مصنوعات و راه اندازی اسکافولد
اکنون ما یک خوشه Kubernetes آماده برای استقرار داریم. در مرحله بعد ما برای یک رجیستری کانتینر برای کانتینرهای فشار و استقرار آماده می کنیم. برای این مراحل، باید یک Artifact Registry (GAR) و skaffold برای استفاده از آن راه اندازی کنیم.
راه اندازی رجیستری مصنوع
به منوی "Artifact Registry" بروید و دکمه ENABLE را فشار دهید.
پس از چند لحظه، مرورگر مخزن GAR را مشاهده خواهید کرد. روی دکمه "ایجاد مخزن" کلیک کنید و نام مخزن را وارد کنید.
در این codelab، من مخزن جدید trace-codelab
را نام میبرم. فرمت این مصنوع "Docker" و نوع مکان "Region" است. منطقه ای نزدیک به منطقه ای را که برای منطقه پیش فرض موتور محاسباتی Google تنظیم کرده اید، انتخاب کنید. به عنوان مثال، این مثال در بالا "us-central1-f" را انتخاب کرد، بنابراین در اینجا "us-central1 (آیووا)" را انتخاب می کنیم. سپس روی دکمه "CREATE" کلیک کنید.
اکنون "trace-codelab" را در مرورگر مخزن مشاهده می کنید.
ما بعداً به اینجا باز خواهیم گشت تا مسیر رجیستری را بررسی کنیم.
راه اندازی داربست
Skaffold ابزاری مفید برای ساختن میکروسرویس هایی است که روی Kubernetes اجرا می شوند. گردش کار ساخت، هل دادن و استقرار کانتینرهای برنامه ها را با مجموعه کوچکی از دستورات کنترل می کند. Skaffold به طور پیشفرض از Docker Registry بهعنوان رجیستری کانتینر استفاده میکند، بنابراین باید skaffold را برای شناسایی GAR در هنگام هل دادن کانتینرها پیکربندی کنید.
دوباره Cloud Shell را باز کنید و تأیید کنید که skaffold نصب شده است. (Cloud Shell به طور پیش فرض skaffold را در محیط نصب می کند.) دستور زیر را اجرا کنید و نسخه skaffold را ببینید.
skaffold version
خروجی فرمان
v1.38.0
اکنون، می توانید مخزن پیش فرض را برای استفاده از skaffold ثبت کنید. برای به دست آوردن مسیر رجیستری، خود را به داشبورد رجیستری Artifact بروید و روی نام مخزنی که در مرحله قبل راه اندازی کرده اید کلیک کنید.
سپس مسیرهای پودر سوخاری را در بالای صفحه خواهید دید. کلیک کنید برای کپی کردن مسیر رجیستری در کلیپ بورد.
با کلیک بر روی دکمه کپی، گفتگو را در پایین مرورگر با پیامی مانند:
"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 انجام دهید.
خلاصه
در این مرحله، محیط Codelab خود را تنظیم می کنید:
- Cloud Shell را راه اندازی کنید
- یک مخزن رجیستری Artifact برای رجیستری کانتینر ایجاد کرد
- برای استفاده از رجیستری کانتینر، skaffold را تنظیم کنید
- یک خوشه Kubernetes ایجاد کرد که در آن میکروسرویس های Codelab اجرا می شوند
بعدی
در مرحله بعد عامل پروفایل پیوسته را در سرویس سرور ابزار می کنید.
3. ساخت، فشار دادن و استقرار میکروسرویس ها
مطالب Codelab را دانلود کنید
در مرحله قبل تمام پیش نیازهای این کد لبه را تنظیم کرده ایم. اکنون شما آماده هستید تا کل میکروسرویس ها را روی آنها اجرا کنید. مواد Codelab در GitHub میزبانی می شوند، بنابراین آنها را با دستور git زیر در محیط Cloud Shell دانلود کنید.
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
- manifests: فایل های مانیفست Kubernetes
- proto: تعریف پروتو برای ارتباط بین مشتری و سرور
- src: دایرکتوری برای کد منبع هر سرویس
- skaffold.yaml: فایل پیکربندی برای skaffold
در این لبه کد، کد منبع واقع در پوشه step4
را به روز می کنید. همچنین می توانید برای تغییرات از ابتدا به کد منبع در پوشه های step[1-6]
مراجعه کنید. (قسمت 1 مرحله 0 تا 4 را پوشش می دهد و قسمت 2 مرحله 5 و 6 را پوشش می دهد)
دستور skaffold را اجرا کنید
در نهایت شما آماده ساخت، فشار دادن و استقرار کل محتوا در خوشه Kubernetes هستید که به تازگی ایجاد کرده اید. به نظر می رسد که شامل چندین مرحله است، اما واقعیت این است که skaffold همه چیز را برای شما انجام می دهد. بیایید آن را با دستور زیر امتحان کنیم:
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
خلاصه
در این مرحله، مواد Codelab را در محیط خود آماده کرده اید و طبق انتظار اجراهای skaffold را تأیید کرده اید.
بعدی
در مرحله بعد، کد منبع سرویس loadgen را برای ابزار دقیق اطلاعات ردیابی تغییر می دهید.
4. ابزار دقیق عامل Cloud Profiler
مفهوم پروفایل سازی مداوم
قبل از توضیح مفهوم پروفایل پیوسته، ابتدا باید مفهوم پروفایل سازی را درک کنیم. پروفایل سازی یکی از روش های تحلیل پویا برنامه (تحلیل برنامه پویا) است و معمولاً در حین توسعه برنامه در فرآیند تست بار و غیره انجام می شود. این یک فعالیت تک شات برای اندازه گیری معیارهای سیستم، مانند استفاده از CPU و حافظه، در طول دوره خاص است. پس از جمع آوری داده های نمایه، توسعه دهندگان آنها را از روی کد تجزیه و تحلیل می کنند.
نمایه سازی پیوسته رویکرد توسعه یافته نمایه سازی معمولی است: نمایه های پنجره کوتاه را به صورت دوره ای در برابر برنامه طولانی اجرا می کند و مجموعه ای از داده های نمایه را جمع آوری می کند. سپس به طور خودکار تجزیه و تحلیل آماری را بر اساس ویژگی خاصی از برنامه، مانند شماره نسخه، منطقه استقرار، زمان اندازه گیری و غیره تولید می کند. جزئیات بیشتر این مفهوم را در مستندات ما خواهید یافت.
از آنجایی که هدف یک برنامه کاربردی در حال اجرا است، راهی برای جمعآوری دورهای دادههای نمایه و ارسال آنها به پشتیبانهایی که دادههای آماری را پس از پردازش میکنند، وجود دارد. این عامل Cloud Profiler است و شما به زودی آن را در سرویس سرور جاسازی خواهید کرد.
جاسازی عامل Cloud Profiler
Cloud Shell Editor را با فشار دادن دکمه باز کنید در سمت راست بالای 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 را مشاهده میکنید، که در قسمت 1 Codelab انجام شده است. اکنون ابزار دقیق برای عامل 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{}
بیاندازیم.
- Service : نام سرویسی که می توانید انتخاب کنید و داشبورد پروفایلر را روشن کنید
- 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" را تایپ کنید و روی نماد Profiler کلیک کنید.
سپس نمودار شعله زیر را خواهید دید.
خلاصه
در این مرحله، عامل Cloud Profiler را در سرویس سرور جاسازی کردید و تأیید کردید که نمودار شعله ایجاد می کند.
بعدی
در مرحله بعد علت گلوگاه در اپلیکیشن را با نمودار شعله بررسی می کنید.
5. نمودار شعله Cloud Profiler را تجزیه و تحلیل کنید
Flame Graph چیست؟
Flame Graph یکی از راه های تجسم داده های پروفایل است. برای توضیح دقیق، لطفاً به سند ما مراجعه کنید، اما خلاصه کوتاه این است:
- هر نوار فراخوانی روش/تابع را در برنامه بیان می کند
- جهت عمودی پشته تماس است. پشته تماس از بالا به پایین رشد می کند
- جهت افقی استفاده از منابع است. هر چه طولانی تر، بدتر
با توجه به آن، بیایید به نمودار شعله به دست آمده نگاه کنیم.
تجزیه و تحلیل نمودار شعله
در بخش قبل، یاد گرفتید که هر نوار در نمودار شعله، فراخوانی تابع/روش را بیان میکند و طول آن به معنای استفاده از منابع در تابع/روش است. نمودار شعله Cloud Profiler نوار را به ترتیب نزولی یا طول را از چپ به راست مرتب می کند، می توانید ابتدا به سمت چپ بالای نمودار نگاه کنید.
در مورد ما، واضح است که 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 تو در تو فراخوانی می شود. بنابراین استفاده از این تابع ممکن است نادرست باشد. بیایید GoDoc regexp را جستجو کنیم.
طبق این سند، 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 از 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 را دوباره بارگذاری کنید و ببینید که چگونه است.
مطمئن شوید که نسخه را به "1.1.0"
تغییر دهید تا فقط پروفایل های نسخه 1.1.0 را ببینید. همانطور که می توانید بگویید، طول نوار GetMatchCount کاهش یافت و نسبت استفاده از زمان CPU (یعنی نوار کوتاه تر شد).
نه تنها با نگاه کردن به نمودار شعله یک نسخه، بلکه می توانید تفاوت های بین دو نسخه را نیز مقایسه کنید.
مقدار لیست کشویی "Compare to" را به "Version" تغییر دهید و مقدار "Compared version" را به "1.0.0"، نسخه اصلی تغییر دهید.
این نوع نمودار شعله را خواهید دید. شکل نمودار مانند 1.1.0 است اما رنگ آمیزی آن متفاوت است. در حالت مقایسه ، معنی رنگ این است:
- آبی : مقدار (مصرف منابع) کاهش یافته است
- نارنجی : مقدار (مصرف منابع) به دست آمده
- خاکستری : خنثی
با توجه به افسانه، اجازه دهید نگاهی دقیق تر به عملکرد بیندازیم. با کلیک بر روی نواری که می خواهید بزرگنمایی کنید، می توانید جزئیات بیشتری را در داخل پشته مشاهده کنید. لطفاً بر روی main.(*serverService).GetMatchCount
نوار GetMatchCount کلیک کنید. همچنین با حرکت بر روی نوار، جزئیات مقایسه را مشاهده خواهید کرد.
می گوید زمان کل CPU از 5.26 ثانیه به 2.88 ثانیه کاهش می یابد (کل 10 ثانیه = پنجره نمونه برداری). این یک پیشرفت بزرگ است!
اکنون می توانید عملکرد برنامه خود را از تجزیه و تحلیل داده های نمایه بهبود ببخشید.
خلاصه
در این مرحله، شما یک ویرایش در سرویس سرور انجام دادید و بهبود حالت مقایسه Cloud Profiler را تایید کردید.
بعدی
در مرحله بعد سورس کد سرویس سرور را به روز کرده و تغییر از نسخه 1.0.0 را تایید می کنید.
7. مرحله اضافی: بهبود در Trace waterfall را تایید کنید
تفاوت بین ردیابی توزیع شده و پروفایل پیوسته
در قسمت 1 از Codelab، تأیید کردید که میتوانید سرویس تنگنا را در میان میکروسرویسها برای یک مسیر درخواست کشف کنید و نمیتوانید علت دقیق گلوگاه را در سرویس خاص کشف کنید. در این قسمت 2 کد لبه، شما آموخته اید که پروفایل سازی مداوم شما را قادر می سازد تا گلوگاه داخل سرویس واحد را از پشته های تماس شناسایی کنید.
در این مرحله، بیایید نمودار آبشار را از روی ردیابی توزیع شده (Cloud Trace) مرور کنیم و تفاوت آن را با پروفایل پیوسته ببینیم.
این نمودار آبشار یکی از ردیابی های با پرس و جو "عشق" است. در کل حدود 6.7 ثانیه (6700 میلی ثانیه) طول می کشد.
و این پس از بهبود برای همان پرس و جو است. همانطور که می گویید، کل تاخیر اکنون 1.5 ثانیه (1500 میلی ثانیه) است که نسبت به اجرای قبلی پیشرفت بسیار زیادی دارد.
نکته مهم در اینجا این است که در نمودار آبشار ردیابی توزیع شده، اطلاعات پشته تماس در دسترس نیست مگر اینکه ابزار شما در همه جا بچرخد. همچنین ردیابیهای توزیعشده فقط بر تأخیر بین سرویسها تمرکز میکنند، در حالی که نمایهسازی مداوم بر منابع رایانه (CPU، حافظه، رشتههای سیستمعامل) یک سرویس متمرکز است.
از جنبه دیگر، ردیابی توزیع شده پایه رویداد است، مشخصات پیوسته آماری است. هر ردیابی نمودار تاخیر متفاوتی دارد و برای دریافت روند تغییرات تاخیر به فرمت متفاوتی مانند توزیع نیاز دارید.
خلاصه
در این مرحله، تفاوت بین ردیابی توزیع شده و پروفایل پیوسته را بررسی کردید.
8. تبریک می گویم
شما با موفقیت ردیابی های توزیع شده را با OpenTelemery ایجاد کردید و تاخیرهای درخواستی را در سراسر میکروسرویس در Google Cloud Trace تأیید کردید.
برای تمرین های طولانی، می توانید موضوعات زیر را خودتان امتحان کنید.
- پیاده سازی کنونی تمام دهانه های ایجاد شده توسط بررسی سلامت را ارسال می کند. (
grpc.health.v1.Health/Check
) چگونه این گستره ها را از Cloud Traces فیلتر می کنید؟ اشاره اینجاست . - گزارشهای رویداد را با دهانهها مرتبط کنید و ببینید که چگونه در 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
پس از حذف خوشه، از پنجره منو، "IAM & Admin" > "Settings" را انتخاب کنید و سپس روی دکمه "SHUT DOWN" کلیک کنید.
سپس شناسه پروژه (نه نام پروژه) را در فرم موجود در گفتگو وارد کرده و خاموش شدن را تأیید کنید.