Instrumen untuk performa yang lebih baik di aplikasi Anda di Go (bagian 2: profiler)

1. Pengantar

e0509e8a07ad5537.png

Terakhir Diperbarui: 14-07-2022

Kemampuan observasi aplikasi

Kemampuan observasi dan Continuous Profiler

Kemampuan observasi adalah istilah yang digunakan untuk mendeskripsikan atribut sistem. Sistem dengan kemampuan observasi memungkinkan tim men-debug sistem mereka secara aktif. Dalam konteks tersebut, tiga pilar observabilitas, yaitu log, metrik, dan rekaman aktivitas, adalah instrumentasi mendasar bagi sistem untuk mendapatkan observabilitas.

Selain tiga pilar kemampuan pengamatan, pembuatan profil berkelanjutan juga merupakan komponen utama lainnya untuk kemampuan pengamatan dan memperluas basis pengguna di industri. Cloud Profiler adalah salah satu pemrakarsa dan menyediakan antarmuka yang mudah untuk melihat perincian metrik performa di stack panggilan aplikasi.

Codelab ini adalah bagian 2 dari rangkaian dan membahas cara menginstrumentasikan agen profiler berkelanjutan. Bagian 1 membahas pelacakan terdistribusi dengan OpenTelemetry dan Cloud Trace, dan Anda akan mempelajari lebih lanjut cara mengidentifikasi hambatan microservice dengan lebih baik di bagian 1.

Yang akan Anda bangun

Dalam codelab ini, Anda akan menginstrumentasikan agen profiler berkelanjutan di layanan server "aplikasi Shakespeare" (alias Shakesapp) yang berjalan di cluster Google Kubernetes Engine. Arsitektur Shakesapp adalah seperti yang dijelaskan di bawah ini:

44e243182ced442f.png

  • Loadgen mengirimkan string kueri ke klien dalam HTTP
  • Klien meneruskan kueri dari loadgen ke server di gRPC
  • Server menerima kueri dari klien, mengambil semua karya Shakespeare dalam format teks dari Google Cloud Storage, menelusuri baris yang berisi kueri, dan menampilkan nomor baris yang cocok kepada klien

Di bagian 1, Anda menemukan bahwa hambatan terjadi di suatu tempat dalam layanan server, tetapi Anda tidak dapat mengidentifikasi penyebab pastinya.

Yang akan Anda pelajari

  • Cara menyematkan agen profiler
  • Cara menyelidiki hambatan di Cloud Profiler

Codelab ini menjelaskan cara menginstrumentasikan agen profiler berkelanjutan di aplikasi Anda.

Yang Anda butuhkan

  • Pengetahuan dasar tentang Go
  • Pengetahuan dasar tentang Kubernetes

2. Penyiapan dan Persyaratan

Penyiapan lingkungan mandiri

Jika belum memiliki Akun Google (Gmail atau Google Apps), Anda harus membuatnya. Login ke Google Cloud Platform console (console.cloud.google.com) dan buat project baru.

Jika Anda sudah memiliki project, klik menu pull-down pilihan project di kiri atas konsol:

7a32e5469db69e9.png

dan klik tombol 'PROJECT BARU' dalam dialog yang dihasilkan untuk membuat project baru:

7136b3ee36ebaf89.png

Jika belum memiliki project, Anda akan melihat dialog seperti ini untuk membuat project pertama:

870a3cbd6541ee86.png

Dialog pembuatan project berikutnya memungkinkan Anda memasukkan detail project baru:

affdc444517ba805.png

Ingat project ID yang merupakan nama unik di semua project Google Cloud (maaf, nama di atas telah digunakan dan tidak akan berfungsi untuk Anda!) Project ID tersebut selanjutnya akan dirujuk di codelab ini sebagai PROJECT_ID.

Selanjutnya, jika Anda belum melakukannya, Anda harus mengaktifkan penagihan di Developers Console untuk menggunakan resource Google Cloud dan mengaktifkan Cloud Trace API.

15d0ef27a8fbab27.png

Menjalankan melalui codelab ini tidak akan menghabiskan biaya lebih dari beberapa dolar, tetapi bisa lebih jika Anda memutuskan untuk menggunakan lebih banyak resource atau jika Anda membiarkannya berjalan (lihat bagian "pembersihan" di akhir dokumen ini). Harga Google Cloud Trace, Google Kubernetes Engine, dan Google Artifact Registry tercantum dalam dokumentasi resmi.

Pengguna baru Google Cloud Platform memenuhi syarat untuk mendapatkan uji coba gratis senilai $300, yang menjadikan codelab ini sepenuhnya gratis.

Penyiapan Google Cloud Shell

Meskipun Google Cloud dan Google Cloud Trace dapat dioperasikan dari jarak jauh menggunakan laptop Anda, dalam codelab ini, kita akan menggunakan Google Cloud Shell, lingkungan command line yang berjalan di Cloud.

Mesin virtual berbasis Debian ini memuat semua alat pengembangan yang akan Anda perlukan. Layanan ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Ini berarti bahwa semua yang Anda perlukan untuk codelab ini adalah browser (ya, ini berfungsi di Chromebook).

Untuk mengaktifkan Cloud Shell dari Cloud Console, cukup klik Aktifkan Cloud Shell gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A (hanya perlu beberapa saat untuk melakukan penyediaan dan terhubung ke lingkungan).

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

Screen Shot 2017-06-14 at 10.13.43 PM.png

Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda sudah diautentikasi dan project sudah ditetapkan ke PROJECT_ID.

gcloud auth list

Output perintah

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

Output perintah

[core]
project = <PROJECT_ID>

Jika, untuk beberapa alasan, project belum disetel, cukup jalankan perintah berikut:

gcloud config set project <PROJECT_ID>

Mencari PROJECT_ID Anda? Periksa ID yang Anda gunakan di langkah-langkah penyiapan atau cari di dasbor Cloud Console:

158fNPfwSxsFqz9YbtJVZes8viTS3d1bV4CVhij3XPxuzVFOtTObnwsphlm6lYGmgdMFwBJtc-FaLrZU7XHAg_ZYoCrgombMRR3h-eolLPcvO351c5iBv506B3ZwghZoiRg6cz23Qw

Cloud Shell juga menetapkan beberapa variabel lingkungan secara default, yang mungkin berguna saat Anda menjalankan perintah di masa mendatang.

echo $GOOGLE_CLOUD_PROJECT

Output perintah

<PROJECT_ID>

Terakhir, tetapkan zona dan konfigurasi project default.

gcloud config set compute/zone us-central1-f

Anda dapat memilih berbagai zona yang berbeda. Untuk informasi selengkapnya, lihat Region & Zona.

Penyiapan bahasa Go

Dalam codelab ini, kita menggunakan Go untuk semua kode sumber. Jalankan perintah berikut di Cloud Shell dan konfirmasi apakah versi Go adalah 1.17+

go version

Output perintah

go version go1.18.3 linux/amd64

Menyiapkan Cluster Google Kubernetes

Dalam codelab ini, Anda akan menjalankan cluster microservice di Google Kubernetes Engine (GKE). Proses codelab ini adalah sebagai berikut:

  1. Download project dasar ke Cloud Shell
  2. Membangun microservice ke dalam container
  3. Mengupload container ke Google Artifact Registry (GAR)
  4. Men-deploy container ke GKE
  5. Ubah kode sumber layanan untuk instrumentasi pelacakan
  6. Lanjutkan ke langkah 2

Aktifkan Kubernetes Engine

Pertama, kita menyiapkan cluster Kubernetes tempat Shakesapp berjalan di GKE, jadi kita perlu mengaktifkan GKE. Buka menu "Kubernetes Engine" dan tekan tombol AKTIFKAN.

548cfd95bc6d344d.png

Sekarang Anda siap membuat cluster Kubernetes.

Membuat cluster Kubernetes

Di Cloud Shell, jalankan perintah berikut untuk membuat cluster Kubernetes. Pastikan nilai zona berada di bawah region yang akan Anda gunakan untuk pembuatan repositori Artifact Registry. Ubah nilai zona us-central1-f jika region repositori Anda tidak mencakup zona tersebut.

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

Output perintah

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

Penyiapan Artifact Registry dan skaffold

Sekarang kita memiliki cluster Kubernetes yang siap untuk deployment. Selanjutnya, kita menyiapkan container registry untuk mengirim dan men-deploy container. Untuk langkah-langkah ini, kita perlu menyiapkan Artifact Registry (GAR) dan skaffold untuk menggunakannya.

Penyiapan Artifact Registry

Buka menu "Artifact Registry" dan tekan tombol AKTIFKAN.

45e384b87f7cf0db.png

Setelah beberapa saat, Anda akan melihat browser repositori GAR. Klik tombol "CREATE REPOSITORY" dan masukkan nama repositori.

d6a70f4cb4ebcbe3.png

Dalam codelab ini, saya menamai repositori baru dengan trace-codelab. Format artefak adalah "Docker" dan jenis lokasi adalah "Region". Pilih region yang dekat dengan region yang Anda tetapkan untuk zona default Google Compute Engine. Misalnya, contoh ini memilih "us-central1-f" di atas, jadi di sini kita memilih "us-central1 (Iowa)". Kemudian, klik tombol "BUAT".

9c2d1ce65258ef70.png

Sekarang Anda melihat "trace-codelab" di browser repositori.

7a3c1f47346bea15.png

Kita akan kembali ke sini nanti untuk memeriksa jalur registri.

Penyiapan Skaffold

Skaffold adalah alat praktis saat Anda mengerjakan pembangunan microservice yang berjalan di Kubernetes. Alat ini menangani alur kerja pembuatan, pengiriman, dan deployment container aplikasi dengan serangkaian kecil perintah. Secara default, Skaffold menggunakan Docker Registry sebagai registry container, jadi Anda perlu mengonfigurasi Skaffold agar mengenali GAR saat mengirim container ke.

Buka kembali Cloud Shell dan konfirmasi apakah skaffold sudah diinstal. (Cloud Shell menginstal skaffold ke lingkungan secara default.) Jalankan perintah berikut dan lihat versi skaffold.

skaffold version

Output perintah

v1.38.0

Sekarang, Anda dapat mendaftarkan repositori default untuk digunakan skaffold. Untuk mendapatkan jalur registri, buka dasbor Artifact Registry dan klik nama repositori yang baru saja Anda siapkan di langkah sebelumnya.

7a3c1f47346bea15.png

Kemudian, Anda akan melihat jejak breadcrumb di bagian atas halaman. Klik ikon e157b1359c3edc06.png untuk menyalin jalur registri ke papan klip.

e0f2ae2144880b8b.png

Saat mengklik tombol salin, Anda akan melihat dialog di bagian bawah browser dengan pesan seperti:

"us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab" telah disalin

Kembali ke cloud shell. Jalankan perintah skaffold config set default-repo dengan nilai yang baru saja Anda salin dari dasbor.

skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab

Output perintah

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

Selain itu, Anda perlu mengonfigurasi registry ke konfigurasi Docker. Jalankan perintah berikut:

gcloud auth configure-docker us-central1-docker.pkg.dev --quiet

Output perintah

{
  "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

Sekarang Anda siap melanjutkan ke langkah berikutnya untuk menyiapkan container Kubernetes di GKE.

Ringkasan

Pada langkah ini, Anda akan menyiapkan lingkungan codelab:

  • Menyiapkan Cloud Shell
  • Membuat repositori Artifact Registry untuk registry container
  • Menyiapkan Skaffold untuk menggunakan container registry
  • Membuat cluster Kubernetes tempat microservice codelab berjalan

Berikutnya

Pada langkah berikutnya, Anda akan menginstrumentasikan agen profiler berkelanjutan di layanan server.

3. Membangun, mengirim, dan men-deploy microservice

Download materi codelab

Pada langkah sebelumnya, kita telah menyiapkan semua prasyarat untuk codelab ini. Sekarang Anda siap menjalankan seluruh microservice di atasnya. Materi codelab dihosting di GitHub, jadi download ke lingkungan Cloud Shell dengan perintah git berikut.

cd ~
git clone https://github.com/ymotongpoo/opentelemetry-trace-codelab-go.git
cd opentelemetry-trace-codelab-go

Struktur direktori project adalah sebagai berikut:

.
├── 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
  • manifes: File manifes Kubernetes
  • proto: definisi proto untuk komunikasi antara klien dan server
  • src: direktori untuk kode sumber setiap layanan
  • skaffold.yaml: File konfigurasi untuk skaffold

Dalam codelab ini, Anda akan memperbarui kode sumber yang ada di folder step4. Anda juga dapat melihat kode sumber di folder step[1-6] untuk mengetahui perubahan sejak awal. (Bagian 1 mencakup langkah 0 hingga langkah 4, dan Bagian 2 mencakup langkah 5 dan 6)

Jalankan perintah skaffold

Terakhir, Anda siap membangun, mengirim, dan men-deploy seluruh konten ke cluster Kubernetes yang baru saja Anda buat. Tampaknya ada beberapa langkah, tetapi sebenarnya skaffold melakukan semuanya untuk Anda. Mari kita coba dengan perintah berikut:

cd step4
skaffold dev

Segera setelah menjalankan perintah, Anda akan melihat output log docker build dan dapat mengonfirmasi bahwa image berhasil di-push ke registry.

Output perintah

...
---> 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

Setelah semua container layanan di-push, deployment Kubernetes akan dimulai secara otomatis.

Output perintah

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

Setelah deployment, Anda akan melihat log aplikasi sebenarnya yang dikeluarkan ke stdout di setiap container seperti ini:

Output perintah

[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

Perhatikan bahwa pada tahap ini, Anda ingin melihat pesan apa pun dari server. Oke, akhirnya Anda siap untuk mulai menginstrumentasi aplikasi dengan OpenTelemetry untuk pelacakan terdistribusi layanan.

Sebelum mulai menginstrumentasi layanan, matikan cluster Anda dengan Ctrl-C.

Output perintah

...
[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

Ringkasan

Pada langkah ini, Anda telah menyiapkan materi codelab di lingkungan Anda dan mengonfirmasi bahwa skaffold berjalan seperti yang diharapkan.

Berikutnya

Pada langkah berikutnya, Anda akan mengubah kode sumber layanan loadgen untuk menginstrumentasi informasi rekaman aktivitas.

4. Pengukuran agen Cloud Profiler

Konsep pembuatan profil berkelanjutan

Sebelum menjelaskan konsep pembuatan profil berkelanjutan, kita perlu memahami konsep pembuatan profil terlebih dahulu. Pembuatan profil adalah salah satu cara untuk menganalisis aplikasi secara dinamis (analisis program dinamis) dan biasanya dilakukan selama pengembangan aplikasi dalam proses pengujian beban dan sebagainya. Ini adalah aktivitas sekali jalan untuk mengukur metrik sistem, seperti penggunaan CPU dan memori, selama periode tertentu. Setelah mengumpulkan data profil, developer menganalisisnya di luar kode.

Pembuatan profil berkelanjutan adalah pendekatan yang diperluas dari pembuatan profil normal: Pembuatan profil ini menjalankan profil jendela pendek terhadap aplikasi yang berjalan lama secara berkala dan mengumpulkan banyak data profil. Kemudian, analisis statistik akan otomatis dibuat berdasarkan atribut tertentu dari aplikasi, seperti nomor versi, zona deployment, waktu pengukuran, dan sebagainya. Anda akan menemukan detail lebih lanjut tentang konsep ini dalam dokumentasi kami.

Karena targetnya adalah aplikasi yang sedang berjalan, ada cara untuk mengumpulkan data profil secara berkala dan mengirimkannya ke beberapa backend yang memproses data statistik setelahnya. Agen tersebut adalah agen Cloud Profiler dan Anda akan segera menyematkannya ke layanan server.

Menyematkan agen Cloud Profiler

Buka Cloud Shell Editor dengan menekan tombol 776a11bfb2122549.png di kanan atas Cloud Shell. Buka step4/src/server/main.go dari penjelajah di panel kiri dan temukan fungsi utama.

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)
        }
}

Dalam fungsi main, Anda akan melihat beberapa kode penyiapan untuk OpenTelemetry dan gRPC, yang telah dilakukan di bagian 1 codelab. Sekarang Anda akan menambahkan instrumentasi untuk agen Cloud Profiler di sini. Seperti yang kita lakukan untuk initTracer(), Anda dapat menulis fungsi bernama initProfiler() agar mudah dibaca.

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)
        }
}

Mari kita perhatikan opsi yang ditentukan dalam objek profiler.Config{}.

  • Layanan: Nama layanan yang dapat Anda pilih dan aktifkan di dasbor profiler
  • ServiceVersion: Nama versi layanan. Anda dapat membandingkan set data profil berdasarkan nilai ini.
  • NoHeapProfiling: menonaktifkan pembuatan profil konsumsi memori
  • NoAllocProfiling: menonaktifkan pembuatan profil alokasi memori
  • NoGoroutineProfiling: menonaktifkan pembuatan profil goroutine
  • NoCPUProfiling: menonaktifkan pembuatan profil CPU

Dalam codelab ini, kita hanya mengaktifkan pembuatan profil CPU.

Sekarang yang perlu Anda lakukan hanyalah memanggil fungsi ini di fungsi main. Pastikan untuk mengimpor paket Cloud Profiler di blok impor.

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
        ...
}

Perhatikan bahwa Anda memanggil fungsi initProfiler() dengan kata kunci go. Karena profiler.Start() memblokir, Anda perlu menjalankannya di goroutine lain. Sekarang sudah siap untuk dibangun. Pastikan untuk menjalankan go mod tidy sebelum deployment.

go mod tidy

Sekarang deploy cluster Anda dengan layanan server baru.

skaffold dev

Biasanya perlu waktu beberapa menit untuk melihat grafik nyala di Cloud Profiler. Ketik "profiler" di kotak penelusuran di bagian atas, lalu klik ikon Profiler.

3d8ca8a64b267a40.png

Kemudian, Anda akan melihat flame graph berikut.

7f80797dddc0128d.png

Ringkasan

Pada langkah ini, Anda menyematkan agen Cloud Profiler ke layanan server dan mengonfirmasi bahwa agen tersebut menghasilkan grafik flame.

Berikutnya

Pada langkah berikutnya, Anda akan menyelidiki penyebab hambatan dalam aplikasi dengan grafik nyala api.

5. Menganalisis grafik flame Cloud Profiler

Apa itu Grafik Flame?

Grafik Flame adalah salah satu cara untuk memvisualisasikan data profil. Untuk penjelasan mendetail, lihat dokumen kami, tetapi ringkasannya adalah:

  • Setiap batang menyatakan panggilan metode/fungsi dalam aplikasi
  • Arah vertikal adalah stack panggilan; stack panggilan bertambah dari atas ke bawah
  • Arah horizontal adalah penggunaan resource; semakin panjang, semakin buruk.

Dengan demikian, mari kita lihat flame graph yang diperoleh.

7f80797dddc0128d.png

Menganalisis Flame Graph

Di bagian sebelumnya, Anda telah mempelajari bahwa setiap batang dalam grafik flame menyatakan panggilan fungsi/metode, dan panjangnya berarti penggunaan resource dalam fungsi/metode. Grafik nyala Cloud Profiler mengurutkan batang dalam urutan menurun atau panjang dari kiri ke kanan, Anda dapat mulai melihat bagian kiri atas grafik terlebih dahulu.

6d90760c6c1183cd.png

Dalam kasus ini, jelas bahwa grpc.(*Server).serveStreams.func1.2 menggunakan sebagian besar waktu CPU, dan dengan melihat tumpukan panggilan dari atas ke bawah, sebagian besar waktu dihabiskan di main.(*serverService).GetMatchCount, yang merupakan pengendali server gRPC di layanan server.

Di bagian GetMatchCount, Anda akan melihat serangkaian fungsi regexp: regexp.MatchString dan regexp.Compile. Mereka berasal dari paket standar: artinya, mereka harus diuji dengan baik dari berbagai sudut pandang, termasuk performa. Namun, hasil di sini menunjukkan bahwa penggunaan resource waktu CPU tinggi di regexp.MatchString dan regexp.Compile. Mengingat fakta tersebut, asumsinya adalah penggunaan regexp.MatchString ada hubungannya dengan masalah performa. Jadi, mari kita baca kode sumber tempat fungsi digunakan.

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
}

Di sinilah regexp.MatchString dipanggil. Dengan membaca kode sumber, Anda mungkin melihat bahwa fungsi dipanggil di dalam loop for bertingkat. Jadi, penggunaan fungsi ini mungkin salah. Mari kita cari GoDoc regexp.

80b8a4ba1931ff7b.png

Menurut dokumen, regexp.MatchString mengompilasi pola ekspresi reguler di setiap panggilan. Jadi, penyebab konsumsi resource yang besar ini kemungkinan adalah hal-hal berikut.

Ringkasan

Pada langkah ini, Anda membuat asumsi penyebab konsumsi resource dengan menganalisis flame graph.

Berikutnya

Pada langkah berikutnya, Anda akan memperbarui kode sumber layanan server dan mengonfirmasi perubahan dari versi 1.0.0.

6. Perbarui kode sumber dan periksa perbedaan grafik nyala api

Perbarui kode sumber

Pada langkah sebelumnya, Anda berasumsi bahwa penggunaan regexp.MatchString ada hubungannya dengan konsumsi resource yang besar. Jadi, mari kita selesaikan masalah ini. Buka kode dan ubah sedikit bagian tersebut.

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
}

Seperti yang Anda lihat, proses kompilasi pola regexp sekarang diekstrak dari regexp.MatchString dan dipindahkan dari loop for bertingkat.

Sebelum men-deploy kode ini, pastikan untuk memperbarui string versi di fungsi 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)
        }
}

Sekarang mari kita lihat cara kerjanya. Deploy cluster dengan perintah skaffold.

skaffold dev

Setelah beberapa saat, muat ulang dasbor Cloud Profiler dan lihat tampilannya.

283cfcd4c13716ad.png

Pastikan untuk mengubah versi ke "1.1.0" agar Anda hanya melihat profil dari versi 1.1.0. Seperti yang dapat Anda lihat, panjang batang GetMatchCount berkurang dan rasio penggunaan waktu CPU (yaitu, batang menjadi lebih pendek).

e3a1456b4aada9a5.png

Tidak hanya dengan melihat flame graph satu versi, Anda juga dapat membandingkan perbedaan antara dua versi.

841dec77d8ba5595.png

Ubah nilai drop-down "Bandingkan dengan" menjadi "Versi" dan ubah nilai "Versi yang dibandingkan" menjadi "1.0.0", versi asli.

5553844292d6a537.png

Anda akan melihat grafik nyala seperti ini. Bentuk grafik sama dengan 1.1.0, tetapi pewarnaannya berbeda. Dalam mode perbandingan, arti warna adalah:

  • Biru: nilai (konsumsi resource) yang dikurangi
  • Oranye: nilai (konsumsi resource) yang diperoleh
  • Abu-abu: netral

Mengingat legenda tersebut, mari kita pelajari lebih lanjut fungsi ini. Dengan mengklik batang yang ingin Anda perbesar, Anda dapat melihat detail selengkapnya di dalam tumpukan. Klik kolom main.(*serverService).GetMatchCount. Selain itu, dengan mengarahkan kursor ke batang, Anda akan melihat detail perbandingan.

ca08d942dc1e2502.png

Dikatakan bahwa total waktu CPU berkurang dari 5,26 detik menjadi 2,88 detik (totalnya adalah 10 detik = jendela pengambilan sampel). Ini adalah peningkatan yang sangat besar.

Sekarang Anda dapat meningkatkan performa aplikasi dari analisis data profil.

Ringkasan

Pada langkah ini, Anda telah melakukan pengeditan di layanan server dan mengonfirmasi peningkatan pada mode perbandingan Cloud Profiler.

Berikutnya

Pada langkah berikutnya, Anda akan memperbarui kode sumber layanan server dan mengonfirmasi perubahan dari versi 1.0.0.

7. Langkah tambahan: Konfirmasi peningkatan di waterfall Aktivitas

Perbedaan antara pelacakan terdistribusi dan pembuatan profil berkelanjutan

Di bagian 1 codelab, Anda mengonfirmasi bahwa Anda dapat mengetahui layanan yang menjadi hambatan di seluruh microservice untuk jalur permintaan dan Anda tidak dapat mengetahui penyebab pasti hambatan di layanan tertentu. Dalam codelab bagian 2 ini, Anda telah mempelajari bahwa pembuatan profil berkelanjutan memungkinkan Anda mengidentifikasi hambatan di dalam satu layanan dari stack panggilan.

Pada langkah ini, mari kita tinjau grafik waterfall dari trace terdistribusi (Cloud Trace) dan lihat perbedaannya dari pembuatan profil berkelanjutan.

Grafik waterfall ini adalah salah satu rekaman aktivitas dengan kueri "love". Totalnya memerlukan waktu sekitar 6,7 detik (6700 md).

e2b7dec25926ee51.png

Dan ini setelah peningkatan untuk kueri yang sama. Seperti yang Anda lihat, total latensi sekarang adalah 1,5 detik (1.500 md), yang merupakan peningkatan besar dari penerapan sebelumnya.

feeb7207f36c7e5e.png

Poin penting di sini adalah bahwa dalam diagram waterfall rekaman aktivitas terdistribusi, informasi stack panggilan tidak tersedia kecuali jika Anda menginstrumentasi rentang di mana pun. Selain itu, rekaman aktivitas terdistribusi hanya berfokus pada latensi di seluruh layanan, sedangkan pembuatan profil berkelanjutan berfokus pada resource komputer (CPU, memori, thread OS) dari satu layanan.

Dalam aspek lain, rekaman aktivitas terdistribusi adalah basis peristiwa, profil berkelanjutan bersifat statistik. Setiap rekaman aktivitas memiliki grafik latensi yang berbeda dan Anda memerlukan format yang berbeda seperti distribusi untuk mendapatkan tren perubahan latensi.

Ringkasan

Pada langkah ini, Anda memeriksa perbedaan antara pelacakan terdistribusi dan pembuatan profil berkelanjutan.

8. Selamat

Anda telah berhasil membuat trace terdistribusi dengan OpenTelemetry dan mengonfirmasi latensi permintaan di seluruh microservice di Google Cloud Trace.

Untuk latihan yang lebih panjang, Anda dapat mencoba topik berikut sendiri.

  • Implementasi saat ini mengirim semua rentang yang dihasilkan oleh health check. (grpc.health.v1.Health/Check) Bagaimana cara memfilter rentang tersebut dari Cloud Trace? Petunjuknya ada di sini.
  • Hubungkan log peristiwa dengan rentang dan lihat cara kerjanya di Google Cloud Trace dan Google Cloud Logging. Petunjuknya ada di sini.
  • Ganti beberapa layanan dengan layanan dalam bahasa lain dan coba instrumentasikan dengan OpenTelemetry untuk bahasa tersebut.

Selain itu, jika Anda ingin mempelajari profiler setelah ini, lanjutkan ke bagian 2. Jika demikian, Anda dapat melewati bagian pembersihan di bawah.

Pembersihan

Setelah menyelesaikan codelab ini, hentikan cluster Kubernetes dan pastikan untuk menghapus project agar Anda tidak dikenai biaya yang tidak terduga di Google Kubernetes Engine, Google Cloud Trace, Google Artifact Registry.

Pertama, hapus cluster. Jika Anda menjalankan cluster dengan skaffold dev, Anda hanya perlu menekan Ctrl-C. Jika Anda menjalankan cluster dengan skaffold run, jalankan perintah berikut:

skaffold delete

Output perintah

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

Setelah menghapus cluster, dari panel menu, pilih "IAM & Admin" > "Settings", lalu klik tombol "SHUT DOWN".

45aa37b7d5e1ddd1.png

Kemudian, masukkan Project ID (bukan Project Name) dalam formulir di dialog dan konfirmasi penonaktifan.