1. Pengantar
Terakhir diperbarui: 14-07-2022
Kemampuan observasi aplikasi
Kemampuan observasi dan Continuous Profiler
Kemampuan observasi adalah istilah yang digunakan untuk menggambarkan atribut suatu sistem. Sistem dengan kemampuan observasi memungkinkan tim men-debug sistem secara aktif. Dalam konteks tersebut, tiga pilar kemampuan observasi; log, metrik, dan trace adalah instrumentasi dasar bagi sistem untuk memperoleh kemampuan observasi.
Selain tiga pilar kemampuan observasi, pembuatan profil berkelanjutan adalah komponen utama lain untuk kemampuan observasi dan memperluas basis pengguna di industri ini. Cloud Profiler adalah salah satu originator dan menyediakan antarmuka yang mudah untuk melihat perincian metrik performa dalam stack panggilan aplikasi.
Codelab ini adalah bagian 2 dari rangkaian ini dan membahas instrumentasi agen profiler berkelanjutan. Bagian 1 membahas pelacakan terdistribusi dengan OpenTelemetry dan Cloud Trace, dan Anda akan mempelajari lebih lanjut cara mengidentifikasi bottleneck microservice secara lebih baik di bagian 1.
Yang akan Anda bangun
Dalam codelab ini, Anda akan melengkapi agen continuous profiler dalam layanan server "Shakespeare application" (alias Shakesapp) yang berjalan di cluster Google Kubernetes Engine. Arsitektur Shakesapp dijelaskan di bawah ini:
- Loadgen mengirimkan string kueri ke klien di HTTP
- Klien meneruskan kueri dari loadgen ke server di gRPC
- Server menerima kueri dari klien, mengambil semua karya Shakespare dalam format teks dari Google Cloud Storage, menelusuri baris yang berisi kueri, dan menampilkan nomor baris yang cocok dengan klien
Di bagian 1, Anda menemukan bahwa bottleneck ada di suatu tempat di layanan server, tetapi Anda tidak dapat mengidentifikasi penyebab pastinya.
Yang akan Anda pelajari
- Cara menyematkan agen profiler
- Cara memeriksa botol neck di Cloud Profiler
Codelab ini menjelaskan cara melengkapi agen continuous profiler dalam aplikasi.
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:
dan klik tombol 'PROJECT BARU' dalam dialog yang dihasilkan untuk membuat project baru:
Jika belum memiliki project, Anda akan melihat dialog seperti ini untuk membuat project pertama:
Dialog pembuatan project berikutnya memungkinkan Anda memasukkan detail project baru:
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 selanjutnya akan dirujuk di codelab ini sebagai PROJECT_ID.
Selanjutnya, jika belum melakukannya, Anda harus mengaktifkan penagihan di Developers Console untuk menggunakan resource Google Cloud dan mengaktifkan Cloud Trace API.
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.
- Harga untuk Google Cloud Operations Suite | Operations Suite
- Harga | Dokumentasi Kubernetes Engine
- Harga Artifact Registry | Dokumentasi Artifact Registry
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 secara jarak jauh dari laptop Anda, dalam codelab ini kita akan menggunakan Google Cloud Shell, yaitu 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 Konsol Cloud, cukup klik Aktifkan Cloud Shell (hanya perlu waktu beberapa saat untuk melakukan penyediaan dan terhubung ke lingkungan).
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:
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 pastikan 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:
- Mendownload project dasar pengukuran ke Cloud Shell
- Membangun microservice ke dalam container
- Mengupload container ke Google Artifact Registry (GAR)
- Men-deploy container ke GKE
- Mengubah kode sumber layanan untuk instrumentasi rekaman aktivitas
- Lanjutkan ke langkah 2
Mengaktifkan Kubernetes Engine
Pertama, kita menyiapkan cluster Kubernetes tempat Shakesapp berjalan di GKE, jadi kita perlu mengaktifkan GKE. Buka menu "Kubernetes Engine" dan tekan tombol ENABLE.
Sekarang Anda siap untuk membuat cluster Kubernetes.
Membuat cluster Kubernetes
Di Cloud Shell, jalankan perintah berikut untuk membuat cluster Kubernetes. Konfirmasi bahwa 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
Artifact Registry dan penyiapan skaffold
Sekarang cluster Kubernetes siap di-deploy. Selanjutnya, kita akan menyiapkan container registry untuk container push dan deploy. Untuk langkah-langkah ini, kita perlu menyiapkan Artifact Registry (GAR) dan skaffold untuk menggunakannya.
Penyiapan Artifact Registry
Buka menu "Artifact Registry" dan tekan tombol ENABLE.
Setelah beberapa saat, Anda akan melihat browser repositori GAR. Klik "CREATE REPOSITORY" dan masukkan nama repositori.
Dalam codelab ini, saya memberi nama repositori baru trace-codelab
. Format artefak adalah "Docker" dan jenis lokasinya 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 pilih
"us-central1 (Iowa)". Kemudian klik tombol "CREATE" tombol.
Sekarang Anda melihat "trace-codelab" di browser repositori.
Kita akan kembali ke sini nanti untuk memeriksa jalur registry.
Penyiapan Skaffold
Skaffold adalah alat yang praktis ketika Anda membangun microservice yang berjalan di Kubernetes. Platform ini menangani alur kerja membangun, mendorong, dan men-deploy container aplikasi dengan sekumpulan kecil perintah. Skaffold secara default menggunakan Docker Registry sebagai container registry, sehingga Anda perlu mengonfigurasi skaffold untuk mengenali GAR saat mengirim container.
Buka Cloud Shell lagi dan pastikan skaffold telah diinstal. (Cloud Shell menginstal skaffold ke dalam lingkungan secara default.) Jalankan perintah berikut dan lihat versi skaffold.
skaffold version
Output perintah
v1.38.0
Sekarang, Anda dapat mendaftarkan repositori default yang akan digunakan oleh skaffold. Untuk mendapatkan jalur registry, buka dasbor Artifact Registry dan klik nama repositori yang baru saja Anda siapkan di langkah sebelumnya.
Kemudian Anda akan melihat jejak breadcrumb di bagian atas halaman. Klik ikon untuk menyalin jalur registry ke papan klip.
Saat mengklik tombol salin, Anda 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 selanjutnya untuk menyiapkan container Kubernetes di GKE.
Ringkasan
Pada langkah ini, Anda akan menyiapkan lingkungan codelab:
- Menyiapkan Cloud Shell
- Membuat repositori Artifact Registry untuk container registry
- Menyiapkan skaffold untuk menggunakan container registry
- Membuat cluster Kubernetes tempat microservice codelab berjalan
Berikutnya
Pada langkah berikutnya, Anda akan melengkapi agen continuous profiler di layanan server.
3. Membangun, mengirim, dan men-deploy microservice
Mendownload 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 materi tersebut 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
- direktori src: untuk kode sumber setiap layanan
- skaffold.yaml: File konfigurasi untuk skaffold
Dalam codelab ini, Anda akan memperbarui kode sumber yang berada di folder step4
. Anda juga dapat merujuk ke kode sumber dalam folder step[1-6]
untuk perubahan dari awal. (Bagian 1 mencakup langkah 0 hingga langkah 4, dan Bagian 2 mencakup langkah 5 dan 6)
Menjalankan perintah skaffold
Terakhir, Anda siap membangun, mengirim, dan men-deploy seluruh konten ke cluster Kubernetes yang baru saja Anda buat. Ini terdengar seperti berisi beberapa langkah, tetapi skaffold yang sebenarnya dapat 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 perintah tersebut berhasil dikirim 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 dikirim, 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 dimunculkan 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
Perlu diketahui bahwa pada tahap ini, Anda ingin melihat semua pesan dari server. Oke, akhirnya Anda siap untuk mulai melengkapi aplikasi dengan OpenTelemetry untuk pelacakan layanan yang terdistribusi.
Sebelum memulai instrumentasi 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 operasi skaffold seperti yang diharapkan.
Berikutnya
Pada langkah berikutnya, Anda akan memodifikasi kode sumber layanan loadgen untuk menginstrumentasikan informasi rekaman aktivitas.
4. Instrumentasi agen Cloud Profiler
Konsep pembuatan profil berkelanjutan
Sebelum menjelaskan konsep pembuatan profil berkelanjutan, kita perlu memahaminya terlebih dahulu. Pembuatan profil adalah salah satu cara untuk menganalisis aplikasi secara dinamis (analisis program dinamis) dan biasanya dilakukan selama pengembangan aplikasi pada proses pengujian beban dan sebagainya. Aktivitas ini adalah aktivitas satu kali untuk mengukur metrik sistem, seperti penggunaan CPU dan memori, selama periode tertentu. Setelah mengumpulkan data profil, developer menganalisisnya dari kode.
Pembuatan profil berkelanjutan adalah pendekatan yang diperluas dari pembuatan profil normal: Profil ini menjalankan profil jendela pendek terhadap aplikasi yang berjalan lama secara berkala dan mengumpulkan banyak data profil. Kemudian, AI akan otomatis menghasilkan analisis statistik berdasarkan atribut aplikasi tertentu, seperti nomor versi, zona deployment, waktu pengukuran, dan seterusnya. Anda dapat menemukan detail konsep lebih lanjut dalam dokumentasi kami.
Karena target adalah aplikasi yang sedang berjalan, ada cara untuk mengumpulkan data profil secara berkala dan mengirimkannya ke beberapa backend yang melakukan pascapemrosesan data statistik. Itu adalah agen Cloud Profiler dan Anda akan segera menyematkannya ke layanan server.
Menyematkan agen Cloud Profiler
Buka Cloud Shell Editor dengan menekan tombol di kanan atas Cloud Shell. Buka
step4/src/server/main.go
dari penjelajah di panel kiri dan temukan fungsi utamanya.
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 codelab bagian 1. 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 pelajari opsi yang ditentukan dalam objek profiler.Config{}
.
- Service: 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 profiling 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 dalam 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()
melakukan pemblokiran, jadi Anda perlu menjalankannya di goroutine lain. Sekarang siap untuk dibangun. Pastikan untuk menjalankan go mod tidy
sebelum deployment.
go mod tidy
Sekarang deploy cluster dengan layanan server baru.
skaffold dev
Biasanya perlu waktu beberapa menit untuk melihat grafik flame di Cloud Profiler. Ketik di "profiler" di kotak penelusuran di bagian atas dan klik ikon Profiler.
Kemudian Anda akan melihat grafik flame berikut.
Ringkasan
Pada langkah ini, Anda menyematkan agen Cloud Profiler ke layanan server dan mengonfirmasi bahwa agen tersebut menghasilkan flame graph.
Berikutnya
Pada langkah berikutnya, Anda akan menyelidiki penyebab bottleneck dalam aplikasi dengan grafik flame.
5. Menganalisis grafik flame Cloud Profiler
Apa itu Flame Graph?
Flame Graph adalah salah satu cara untuk memvisualisasikan data profil. Untuk penjelasan mendetail, lihat dokumen kami, tetapi ringkasan singkatnya adalah:
- Setiap batang mengekspresikan panggilan metode/fungsi dalam aplikasi
- Arah vertikal adalah stack panggilan; stack panggilan berkembang dari atas ke bawah
- Arah horizontal adalah penggunaan resource; semakin lama, semakin buruk.
Berdasarkan hal itu, mari kita lihat grafik flame yang diperoleh.
Menganalisis Grafik Flame
Di bagian sebelumnya, Anda belajar bahwa setiap batang dalam grafik flame mengekspresikan panggilan fungsi/metode, dan panjangnya berarti penggunaan resource dalam fungsi/metode. Grafik flame Cloud Profiler mengurutkan batang dalam urutan menurun atau panjang dari kiri ke kanan, Anda dapat mulai melihat bagian kiri atas grafik terlebih dahulu.
Dalam kasus kita, jelas bahwa grpc.(*Server).serveStreams.func1.2
menghabiskan sebagian besar waktu CPU, dan dengan melihat stack panggilan dari atas ke bawah, yang menghabiskan sebagian besar waktu 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
. Metrik ini berasal dari paket standar: yaitu, uji coba tersebut harus diuji dengan baik dari banyak sudut pandang, termasuk performa. Namun, hasilnya di sini menunjukkan bahwa penggunaan resource waktu CPU tinggi di regexp.MatchString
dan regexp.Compile
. Dengan fakta tersebut, asumsi di sini adalah penggunaan regexp.MatchString
ada hubungannya dengan masalah performa. Jadi mari kita baca kode sumber
tempat fungsi tersebut 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 }
Ini adalah tempat regexp.MatchString
dipanggil. Dengan membaca kode sumber, Anda mungkin memperhatikan bahwa fungsi tersebut dipanggil di dalam for-loop bertingkat. Jadi penggunaan fungsi ini mungkin salah. Mari kita cari GoDoc dari regexp.
Menurut dokumen ini, regexp.MatchString
mengompilasi pola ekspresi reguler dalam setiap panggilan. Jadi, penyebab konsumsi resource yang besar terdengar seperti ini.
Ringkasan
Pada langkah ini, Anda membuat asumsi penyebab konsumsi resource dengan menganalisis grafik flame.
Berikutnya
Pada langkah berikutnya, Anda akan memperbarui kode sumber layanan server dan mengonfirmasi perubahan dari versi 1.0.0.
6. Mengupdate kode sumber dan membedakan grafik flame
Memperbarui kode sumber
Pada langkah sebelumnya, Anda membuat asumsi 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, kini proses kompilasi pola regexp diekstrak dari regexp.MatchString
dan dipindahkan dari loop for bertingkat.
Sebelum men-deploy kode ini, pastikan untuk mengupdate 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. Men-deploy cluster dengan perintah skaffold.
skaffold dev
Setelah beberapa saat, muat ulang dasbor Cloud Profiler dan lihat bagaimana rasanya.
Pastikan untuk mengubah versi ke "1.1.0"
agar Anda hanya melihat profil dari versi 1.1.0. Seperti yang Anda lihat, panjang batang GetMatchCount berkurang dan rasio penggunaan waktu CPU (yaitu batang menjadi lebih pendek).
Tidak hanya dengan melihat grafik flame dari satu versi, Anda juga dapat membandingkan perbedaan antara dua versi tersebut.
Ubah nilai "Compare to" menu drop-down ke "Versi" dan ubah nilai "{i>Comparisond Version<i}" ke "1.0.0", versi aslinya.
Anda akan melihat grafik api seperti ini. Bentuk grafiknya sama seperti 1.1.0 tetapi pewarnaannya berbeda. Dalam mode perbandingan, arti warnanya adalah:
- Biru: nilai (konsumsi resource) yang dikurangi
- Oranye: nilai (konsumsi resource) yang diperoleh
- Abu-abu: netral
Berdasarkan legenda, mari kita pelajari fungsinya lebih lanjut. Dengan mengklik panel yang ingin diperbesar, Anda dapat melihat detail selengkapnya di dalam kelompok. Klik main.(*serverService).GetMatchCount
batang. Selain itu, dengan mengarahkan kursor ke batang, Anda akan melihat detail perbandingan.
Dikatakan bahwa total waktu CPU berkurang dari 5,26 detik menjadi 2,88 detik (totalnya adalah 10 detik = jendela pengambilan sampel). Ini adalah peningkatan besar!
Sekarang Anda dapat meningkatkan performa aplikasi dari analisis data profil.
Ringkasan
Pada langkah ini, Anda 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 Trace
Perbedaan antara pelacakan terdistribusi dan pembuatan profil berkelanjutan
Di bagian 1 codelab, Anda mengonfirmasi bahwa Anda dapat mengetahui layanan bottleneck di seluruh microservice untuk jalur permintaan dan tidak dapat mengetahui penyebab pasti bottleneck di layanan tertentu. Di codelab bagian 2 ini, Anda telah mempelajari bahwa pembuatan profil berkelanjutan memungkinkan Anda mengidentifikasi bottleneck di dalam satu layanan dari stack panggilan.
Pada langkah ini, mari kita tinjau grafik waterfall dari pelacakan terdistribusi (Cloud Trace) dan lihat perbedaannya dari pembuatan profil berkelanjutan.
Grafik waterfall ini adalah salah satu trace dengan kueri "love". Waktu yang diperlukan sekitar 6,7 dtk (6700 md) secara total.
Hal ini dilakukan setelah peningkatan untuk kueri yang sama. Seperti yang Anda lihat, total latensi kini menjadi 1,5 dtk (1.500 md), yang merupakan peningkatan besar dari implementasi sebelumnya.
Poin penting di sini adalah bahwa dalam diagram waterfall pelacakan terdistribusi, informasi stack panggilan tidak tersedia kecuali jika instrumen Anda tersebar di mana-mana. Selain itu, pelacakan 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, pelacakan terdistribusi adalah basis peristiwa, profil berkelanjutan bersifat statistik. Setiap trace memiliki grafik latensi yang berbeda dan Anda memerlukan format yang berbeda seperti distribusi untuk mendapatkan tren perubahan latensi.
Ringkasan
Pada langkah ini, Anda telah memeriksa perbedaan antara pelacakan terdistribusi dan pembuatan profil berkelanjutan.
8. Selamat
Anda telah berhasil membuat trace terdistribusi dengan OpenTelemery dan latensi permintaan yang dikonfirmasi di seluruh microservice di Google Cloud Trace.
Untuk latihan yang diperpanjang, Anda dapat mencoba sendiri topik berikut.
- Penerapan saat ini mengirimkan semua span yang dihasilkan oleh health check. (
grpc.health.v1.Health/Check
) Bagaimana cara memfilter span tersebut dari Cloud Trace? Petunjuknya ada di sini. - Kaitkan log peristiwa dengan span 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 cobalah melengkapinya 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 codelab ini, hentikan cluster Kubernetes dan pastikan untuk menghapus project sehingga Anda tidak menerima tagihan yang tidak terduga di Google Kubernetes Engine, Google Cloud Trace, Google Artifact Registry.
Pertama, hapus cluster. Jika 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" > "Setelan", lalu klik "MATIKAN" tombol.
Kemudian masukkan Project ID (bukan Nama Project) dalam formulir di dialog dan konfirmasi penonaktifan.