Go'daki uygulamanızda daha iyi performans elde etmenizi sağlayan araç (1. bölüm: trace)

Go'daki uygulamanızda daha iyi performans elde etmenizi sağlayan araç (1. bölüm:
trace)

Bu codelab hakkında

subjectSon güncelleme Tem 25, 2022
account_circleYazan: Yoshi Yamaguchi

1. Giriş

505827108874614d.png

Son güncelleme tarihi: 15.07.2022

Uygulamanın gözlemlenebilirliği

Gözlemlenebilirlik ve OpenTemetri

Gözlemlenebilirlik, bir sistemin özelliklerini tanımlamak için kullanılan terimdir. Gözlemlenebilirliğe sahip bir sistem, ekiplerin sistemlerinde etkin bir şekilde hata ayıklamasına olanak tanır. Bu bağlamda, gözlemlenebilirliğin üç ayağı; günlükler, metrikler ve izler, sistemin gözlemlenebilirlik elde etmesi için temel araçlardır.

OpenTelemetry, gözlemlenebilirliğin gerektirdiği telemetri verilerinin (günlükler, metrikler ve izler) enstrümantasyonunu ve dışa aktarılmasını hızlandıran bir spesifikasyonlar, kitaplıklar ve aracılar grubudur. OpenTelemetry, CNCF kapsamındaki açık standart ve topluluk odaklı bir projedir. Projenin ve ekosisteminin sağladığı kitaplıklardan yararlanan geliştiriciler, uygulamalarını satıcıdan bağımsız bir şekilde ve birden fazla mimariye karşı enstrümantasyonlarını kullanarak gerçekleştirebilirler.

Gözlemlenebilirliğin üç temel dayanağına ek olarak, sürekli profil çıkarma gözlemlenebilirlik açısından başka bir temel bileşendir ve sektördeki kullanıcı tabanını genişletmektedir. Kaynaklardan biri olan Cloud Profiler, uygulama çağrı yığınlarındaki performans metriklerini ayrıntılı olarak incelemek için kolay bir arayüz sunar.

Bu codelab, serinin 1. bölümüdür ve OpenTelemetry ve Cloud Trace ile mikro hizmetlerdeki dağıtılmış izlerin enstrümantasyonunu ele alır. 2. bölümde, Cloud Profiler ile sürekli profil oluşturma ele alınmaktadır.

Dağıtılmış İz

Günlükler, metrikler ve izler arasında, sistemdeki sürecin belirli bir bölümünün gecikmesini bildiren telemetri telemetridir. Özellikle mikro hizmet çağında, dağıtılmış izleme, genel olarak dağıtılmış sistemdeki gecikme sorunlarını tespit etmek için güçlü bir etmendir.

Dağıtılmış izleri analiz ederken iz verilerini görselleştirme, genel sistem gecikmelerini bir bakışta anlamanın anahtarıdır. Dağıtılmış izlemede, sistem giriş noktasına yapılan tek bir isteği birden çok aralık içeren Trace biçiminde işlemek için bir dizi çağrıyı ele alırız.

Yayılma, dağıtılmış bir sistemde yapılan tek bir iş birimini temsil eder ve başlangıç ve bitiş zamanlarını kaydeder. Aralıklar genellikle birbirleriyle hiyerarşik ilişkilere sahiptir. Aşağıdaki resimde daha küçük aralıkların alt aralıkları, geniş /mesajlar aralığının alt aralıklarıdır ve bir sistemdeki çalışmanın yolunu gösteren tek bir İzde birleştirilmiştir.

Bir iz

Dağıtılmış izleme arka ucu seçeneklerinden biri olan Google Cloud Trace, Google Cloud'daki diğer ürünlerle iyi entegre edilmiştir.

Oluşturacaklarınız

Bu codelab'de "Shakespeare uygulaması" adlı hizmetlerdeki enstrüman izleme bilgilerini kullanacaksınız. (diğer adıyla Shakesapp) olan bir uygulamadır. Shakesapp'in mimarisi aşağıda açıklandığı gibidir:

44e243182ced442f.png

  • Loadgen, HTTP'de istemciye bir sorgu dizesi gönderir
  • İstemciler sorguyu gRPC'deki yük kaynağından sunucuya iletir
  • Sunucu; istemciden gelen sorguyu kabul eder, tüm Shakespare eserlerini Google Cloud Storage'dan metin biçiminde getirir, sorguyu içeren satırları arar ve istemciyle eşleşen satırın numarasını döndürür.

İzleme bilgilerini istek genelinde kullanacaksınız. Bundan sonra, sunucuya bir profil aracı aracısı yerleştirecek ve tıkanıklığı araştıracaksınız.

Neler öğreneceksiniz?

  • Go projesindeki OpenTelemetry Trace kitaplıklarını kullanmaya başlama
  • Kitaplıkla aralık oluşturma
  • Aralık bağlamlarını kablo genelinde uygulama bileşenleri arasında yayma
  • İz verileri Cloud Trace'e nasıl gönderilir?
  • Cloud Trace'te izi analiz etme

Bu codelab'de, mikro hizmetlerinizi nasıl kullanacağınız açıklanmaktadır. Anlaşılmasını kolaylaştırmak için bu örnekte yalnızca 3 bileşen (yük oluşturucu, istemci ve sunucu) vardır. Ancak bu codelab'de açıklanan süreci daha karmaşık ve büyük sistemlere de uygulayabilirsiniz.

Gerekenler

  • Go hakkında temel düzeyde bilgi
  • Kubernetes hakkında temel bilgiler

2. Kurulum ve Gereksinimler

Kendi hızınızda ortam kurulumu

Google Hesabınız (Gmail veya Google Apps) yoksa bir hesap oluşturmanız gerekir. Google Cloud Platform konsolunda ( console.cloud.google.com) oturum açın ve yeni bir proje oluşturun.

Zaten bir projeniz varsa konsolun sol üst köşesindeki proje seçimi açılan menüsünü tıklayın:

7a32e5469db69e9.png

Sonra ‘YENİ PROJE’yi tıklayın. düğmesini tıklayın:

7136b3ee36ebaf89.png

Henüz projeniz yoksa ilk projenizi oluşturmak için şuna benzer bir iletişim kutusu görmeniz gerekir:

870a3cbd6541ee86.png

Sonraki proje oluşturma iletişim kutusu yeni projenizin ayrıntılarını girmenize olanak tanır:

affdc444517ba805.png

Tüm Google Cloud projeleri için benzersiz bir ad olan proje kimliğini unutmayın (yukarıdaki ad daha önce alınmış ve size uygun olmayacaktır!). Bu kod, bu codelab'in ilerleyen bölümlerinde PROJECT_ID olarak adlandırılacaktır.

Sonraki adımda, henüz yapmadıysanız Developers Console'da faturalandırmayı etkinleştirmeniz ve Google Cloud kaynaklarını kullanmak ve Cloud Trace API'yi etkinleştirmek için yapmanız gerekir.

15d0ef27a8fbab27.png

Bu codelab'i çalıştırmanın maliyeti birkaç dolardan fazla değildir. Ancak daha fazla kaynak kullanmaya karar verirseniz veya bu kaynakları çalışır durumda bırakırsanız daha yüksek ücret ödemeniz gerekebilir (bu belgenin sonundaki "temizlik" bölümüne bakın). Google Cloud Trace, Google Kubernetes Engine ve Google Artifact Registry'nin fiyatları resmi belgelerde belirtilmiştir.

Yeni Google Cloud Platform kullanıcıları, bu codelab'i tamamen ücretsiz hale getirecek 300 ABD doları değerindeki ücretsiz denemeden yararlanabilir.

Google Cloud Shell Kurulumu

Google Cloud ve Google Cloud Trace, dizüstü bilgisayarınızdan uzaktan çalıştırılabilse de bu codelab'de Cloud'da çalışan bir komut satırı ortamı olan Google Cloud Shell'i kullanacağız.

Bu Debian tabanlı sanal makine, ihtiyacınız olan tüm geliştirme araçlarıyla yüklüdür. 5 GB boyutunda kalıcı bir ana dizin sunar ve Google Cloud'da çalışarak ağ performansını ve kimlik doğrulamasını büyük ölçüde iyileştirir. Yani bu codelab'de ihtiyacınız olan tek şey bir tarayıcıdır (Evet, Chromebook'ta çalışır).

Cloud Console'dan Cloud Shell'i etkinleştirmek için Cloud Shell'i Etkinleştir'i gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A tıklamanız yeterlidir (sağlanması ve ortama bağlanması birkaç dakika sürer).

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

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

Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin PROJECT_ID olarak ayarlanmış olduğunu göreceksiniz.

gcloud auth list

Komut çıkışı

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

Komut çıkışı

[core]
project = <PROJECT_ID>

Herhangi bir nedenle proje ayarlanmamışsa şu komutu vermeniz yeterlidir:

gcloud config set project <PROJECT_ID>

PROJECT_ID cihazınızı mı arıyorsunuz? Kurulum adımlarında kullandığınız kimliği kontrol edin veya Cloud Console kontrol panelinden arayın:

158fNPfwSxsFqz9YbtJVZes8viTS3d1bV4CVhij3XPxuzVFOtTObnwsphlm6lYGmgdMFwBJtc-FaLrZU7XHAg_ZYoCrgombMRR3h-eolLPcvO351c5iBv506B3ZwghZoiRg6cz23Qw

Cloud Shell bazı ortam değişkenlerini de varsayılan olarak ayarlar. Bu değişkenler, gelecekte komut çalıştırdığınızda işinize yarayabilir.

echo $GOOGLE_CLOUD_PROJECT

Komut çıkışı

<PROJECT_ID>

Son olarak, varsayılan alt bölgeyi ve proje yapılandırmasını ayarlayın.

gcloud config set compute/zone us-central1-f

Çeşitli farklı alt bölgeler seçebilirsiniz. Daha fazla bilgi için Bölgeler ve Bölgeler.

Go dil kurulumu

Bu codelab'de tüm kaynak kodları için Go'yu kullanacağız. Cloud Shell'de aşağıdaki komutu çalıştırın ve Go sürümünün 1.17 veya üzeri bir sürüm olup olmadığını onaylayın.

go version

Komut çıkışı

go version go1.18.3 linux/amd64

Google Kubernetes Kümesi oluşturma

Bu codelab'de, Google Kubernetes Engine'de (GKE) bir mikro hizmet kümesi çalıştıracaksınız. Bu codelab'de süreç aşağıdaki gibidir:

  1. Temel projeyi Cloud Shell'e indirme
  2. Container'larda mikro hizmetler derleme
  3. Kapsayıcıları Google Artifact Registry'ye (GAR) yükleme
  4. Container'ları GKE'ye dağıtma
  5. İzleme araçları için hizmetlerin kaynak kodunu değiştirin
  6. 2. adıma git

Kubernetes Engine'i etkinleştirme

İlk olarak Shakesapp'in GKE'de çalıştığı bir Kubernetes kümesi oluşturmak için GKE'yi etkinleştirmemiz gerekiyor. "Kubernetes Engine" menüsüne gidin ETKİNLEŞTİR düğmesine basın.

548cfd95bc6d344d.png

Artık Kubernetes kümesi oluşturmaya hazırsınız.

Kubernetes kümesi oluşturma

Cloud Shell'de, Kubernetes kümesi oluşturmak için aşağıdaki komutu çalıştırın. Lütfen Artifact Registry deposu oluşturmak için kullanacağınız bölge değerinin altında olduğunu onaylayın. Depo bölgeniz, alt bölgeyi kapsamıyorsa us-central1-f alt bölge değerini değiştirin.

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

Komut çıkışı

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 ve skaffold kurulumu

Artık dağıtıma hazır bir Kubernetes kümemiz var. Şimdi, container'ları push ve dağıtma işlemleri için container kaydı için hazırlayacağız. Bu adımlar için bir Artifact Registry (GAR) oluşturmamız ve bunu kullanmak için kaykay yapmamız gerekir.

Artifact Registry kurulumu

"Artifact Registry" menüsüne gidin ETKİNLEŞTİR düğmesine basın.

45e384b87f7cf0db.png

Bir süre sonra GAR'nin depo tarayıcısını göreceksiniz. "REPOSITORY OLUŞTUR"u tıklayın. düğmesini tıklayın ve deponun adını girin.

d6a70f4cb4ebcbe3.png

Bu codelab'de yeni depoyu trace-codelab olarak adlandırıyorum. Yapının biçimi "Docker"dır ve konum türü "Bölge" ise. Google Compute Engine varsayılan alt bölgesi için belirlediğinize yakın bölgeyi seçin. Örneğin, bu örnek "us-central1-f"yi seçti Burada "us-central1 (Iowa)"yı seçiyoruz. Ardından "OLUŞTUR"u tıklayın. düğmesini tıklayın.

9c2d1ce65258ef70.png

Artık "trace-codelab"i görüyorsunuz. kod deposunda toplanır.

7a3c1f47346bea15.png

Kayıt defteri yolunu kontrol etmek için daha sonra buraya geri döneceğiz.

Skaffold kurulumu

Skaffold, Kubernetes üzerinde çalışan mikro hizmetler oluştururken kullanabileceğiniz pratik bir araçtır. Uygulama container'larını oluşturma, aktarma ve dağıtma iş akışını küçük bir komut grubuyla yönetir. Skaffold, container kayıt defteri olarak varsayılan olarak Docker Registry'yi kullanır. Bu nedenle, container'lara aktarılırken GAR'yi tanımak için skaffold'u yapılandırmanız gerekir.

Cloud Shell'i tekrar açın ve skaffold yüklü olup olmadığını onaylayın. (Cloud Shell'i varsayılan olarak ortama yükler.) Aşağıdaki komutu çalıştırarak skaffold sürümünü görebilirsiniz.

skaffold version

Komut çıkışı

v1.38.0

Şimdi, varsayılan depoyu skaf Fold'un kullanması için kaydedebilirsiniz. Kayıt defteri yolunu almak için Artifact Registry kontrol paneline gidin ve önceki adımda ayarladığınız deponun adını tıklayın.

7a3c1f47346bea15.png

Ardından, sayfanın üst kısmında içerik haritası yollarını görürsünüz. Kayıt defteri yolunu panoya kopyalamak için e157b1359c3edc06.png simgesini tıklayın.

e0f2ae2144880b8b.png

Kopyala düğmesini tıkladığınızda, tarayıcının en altında aşağıdakine benzer bir mesaj içeren bir iletişim kutusu görürsünüz:

&quot;us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab&quot; kopyalandı

Cloud Shell'e geri dönün. Kontrol panelinden kopyaladığınız değerle skaffold config set default-repo komutunu çalıştırın.

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

Komut çıkışı

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

Ayrıca, kayıt defterini Docker yapılandırmasına göre yapılandırmanız gerekir. Aşağıdaki komutu çalıştırın:

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

Komut çıkışı

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

Artık GKE'de Kubernetes container'ı oluşturma adımına geçebilirsiniz.

Özet

Bu adımda codelab ortamınızı kuracaksınız:

  • Cloud Shell'i kurma
  • Container kayıt defteri için Artifact Registry deposu oluşturuldu
  • Container kayıt defterini kullanmak için skaffold'u ayarlama
  • codelab mikro hizmetlerinin çalıştırıldığı bir Kubernetes kümesi oluşturuldu

Sonraki bölüm

Bir sonraki adımda mikro hizmetlerinizi derleyecek, kümeye aktaracak ve dağıtacaksınız.

3. Mikro hizmetleri derleme, aktarma ve dağıtma

Codelab materyalini indirin

Önceki adımda bu codelab için tüm ön koşulları ayarladık. Artık tüm mikro hizmetleri bunların üzerinde çalıştırmaya hazırsınız. Codelab materyali GitHub'da barındırıldığından aşağıdaki git komutuyla verileri Cloud Shell ortamına indirin.

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

Projenin dizin yapısı aşağıdaki gibidir:

.
├── 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
  • manifest'ler: Kubernetes manifest dosyaları
  • proto: istemci ve sunucu arasındaki iletişimin proto tanımı
  • src: her hizmetin kaynak kodu için dizinler
  • skaffold.yaml: Skaffold için yapılandırma dosyası

Bu codelab'de, step0 klasörünün altında bulunan kaynak kodunu güncelleyeceksiniz. Aşağıdaki adımlarda verilen yanıtlar için step[1-6] klasöründeki kaynak koda da bakabilirsiniz. (1. Bölüm 0. adımdan 4. adıma, 2. Bölüm 5. ve 6. adımları kapsar)

skaffold komutunu çalıştırma

Artık tüm içeriği derlemeye, aktarmaya ve az önce oluşturduğunuz Kubernetes kümesine dağıtmaya hazırsınız. Bu araç birden fazla adım içeriyormuş gibi görünüyor, ancak gerçek kaykay, her şeyi sizin için yapıyor. Bunu aşağıdaki komutla deneyelim:

cd step0
skaffold dev

Komutu çalıştırır çalıştırmaz docker build günlük çıkışını görürsünüz ve bunların kayıt defterine başarıyla aktarıldığını onaylayabilirsiniz.

Komut çıkışı

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

Tüm hizmet container'ları aktarıldıktan sonra Kubernetes dağıtımları otomatik olarak başlar.

Komut çıkışı

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

Dağıtımdan sonra her container'da stdout'a yayınlanan gerçek uygulama günlüklerini aşağıdaki gibi görürsünüz:

Komut çıkışı

[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

Bu aşamada, sunucudan gelen tüm iletileri görmek istediğinizi unutmayın. Tamam, nihayet hizmetlerin dağıtılmış izlemesi için OpenTelemetry ile uygulamanıza enstrümantasyon yapmaya hazırsınız.

Hizmetin enstrümantasyonuna başlamadan önce lütfen Ctrl-C tuşlarına basarak kümenizi kapatın.

Komut çıkışı

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

Özet

Bu adımda, codelab materyalini ortamınızda hazırladınız ve patenin beklendiği gibi çalıştığını onayladınız.

Sonraki bölüm

Sonraki adımda iz bilgilerini kullanmak için loadgen hizmetinin kaynak kodunu değiştireceksiniz.

4. HTTP Enstrümantasyonu

İz enstrümantasyonu ve yayılımı kavramı

Kaynak kodunu düzenlemeden önce, dağıtılmış izlerin nasıl çalıştığını basit bir diyagramda kısaca açıklayayım.

6be42e353b9bfd1d.png

Bu örnekte, İzleme ve Aralık bilgilerini Cloud Trace'e aktarmak ve iz bağlamını, istekteki loadgen hizmetinden sunucu hizmetine yaymak için kodda işlemleri gerçekleştiriyoruz.

Uygulamaların, aynı iz kimliğine sahip tüm aralıkları tek izde derlemesi için Cloud Trace'in işlemesi için İzleme Kimliği ve Span Kimliği gibi İz meta verileri göndermesi gerekir. Ayrıca uygulamanın, aşağı akış hizmetleri isteğinde bulunurken iz bağlamlarını (üst aralığın İzleme Kimliği ve Aralık Kimliği kombinasyonu) yayması gerekir. Böylece kullanıcılar hangi izleme bağlamını işlediklerini öğrenebilir.

OpenTelemetry size şu konularda yardımcı olur:

  • benzersiz İzleme Kimliği ve Aralık Kimliği oluşturmak için
  • arka uca iz kimliğini ve yayılma kimliğini aktarmak için
  • izleme bağlamlarını diğer hizmetlere yaymak için
  • Böylece, izleri analiz etmeye yardımcı olan ekstra meta veriler yerleştirmek için

OpenTelemetry Trace'teki Bileşenler

b01f7bb90188db0d.png

OpenTelemetry ile uygulama izleme işlemi aşağıdaki gibidir:

  1. Dışa aktarıcı oluşturma
  2. Dışa aktarıcı için 1 bağlantıda bir TracerProvider oluşturun ve global olarak ayarlayın.
  3. Yayılım yöntemini ayarlamak için TextMapPropagaror'ı ayarlayın
  4. TracerProvider'dan Tracer alma
  5. İzleyiciden Aralık Oluşturma

Şimdilik, her bileşenin ayrıntılı özelliklerini anlamanız gerekmez ancak unutulmaması gereken en önemli noktalar şunlardır:

  • buradaki dışa aktarıcı TracerProvider'a bağlanabilir
  • TracerProvider, iz örnekleme ve dışa aktarmayla ilgili tüm yapılandırmayı içerir
  • tüm izler, Tracer nesnesinde gruplanır

Bunu anladıktan sonra gerçek kodlama işlemine geçelim.

Enstrüman ilk aralık

Enstrüman yük oluşturma hizmeti

Cloud Shell'in sağ üst tarafında bulunan düğmeye 776a11bfb2122549.pngbasarak Cloud Shell Düzenleyici'yi açın. Sol bölmedeki gezginden step0/src/loadgen/main.go uygulamasını açın ve ana işlevi bulun.

step0/src/loadgen/main.go

func main() {
        ...
        for range t.C {
                log.Printf("simulating client requests, round %d", i)
                if err := run(numWorkers, numConcurrency); err != nil {
                        log.Printf("aborted round with error: %v", err)
                }
                log.Printf("simulated %d requests", numWorkers)
                if numRounds != 0 && i > numRounds {
                        break
                }
                i++
        }
}

Ana işlevde, run fonksiyonunu çağıran döngüyü görürsünüz. Geçerli uygulamada, bölümde işlev çağrısının başlangıcını ve sonunu kaydeden 2 günlük satırı bulunur. Şimdi fonksiyon çağrısının gecikmesini izlemek için Span bilgilerini kullanalım.

Önceki bölümde belirtildiği gibi, önce OpenTelemetry için tüm yapılandırmaları ayarlayalım. OpenTelemetry paketlerini aşağıdaki gibi ekleyin:

step0/src/loadgen/main.go

import (
        "context" // step1. add packages
        "encoding/json"
        "fmt"
        "io"
        "log"
        "math/rand"
        "net/http"
        "net/url"
        "time"
        // step1. add packages
        "go.opentelemetry.io/otel"
        "go.opentelemetry.io/otel/attribute"
        stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
        "go.opentelemetry.io/otel/propagation"
        sdktrace "go.opentelemetry.io/otel/sdk/trace"
        semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
        "go.opentelemetry.io/otel/trace"
        // step1. end add packages
)

Okunabilirlik için initTracer adında bir kurulum işlevi oluşturup main işlevinde bu işlevi çağırıyoruz.

step0/src/loadgen/main.go

// step1. add OpenTelemetry initialization function
func initTracer() (*sdktrace.TracerProvider, error) {
        // create a stdout exporter to show collected spans out to stdout.
        exporter, err := stdout.New(stdout.WithPrettyPrint())
        if err != nil {
                return nil, err
        }

        // for the demonstration, we use AlwaysSmaple sampler to take all spans.
        // do not use this option in production.
        tp := sdktrace.NewTracerProvider(
                sdktrace.WithSampler(sdktrace.AlwaysSample()),
                sdktrace.WithBatcher(exporter),
        )
        otel.SetTracerProvider(tp)
        otel.SetTextMapPropagator(propagation.TraceContext{})
        return tp, nil
}

OpenTelemetry'yi ayarlama prosedürünün önceki bölümde açıklandığı gibi olduğunu görebilirsiniz. Bu uygulamada, tüm iz bilgilerini yapılandırılmış bir biçimde stdout'a aktaran bir stdout dışa aktarıcısı kullanırız.

Ardından, bunu ana işlevden çağırırsınız. initTracer() hattını arayın ve uygulamayı kapattığınızda TracerProvider.Shutdown() işlevini çağırdığınızdan emin olun.

step0/src/loadgen/main.go

func main() {
        // step1. 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)
                }
        }()
        // step1. end setup

        log.Printf("starting worder with %d workers in %d concurrency", numWorkers, numConcurrency)
        log.Printf("number of rounds: %d (0 is inifinite)", numRounds)
        ...

Kurulumu tamamladıktan sonra benzersiz bir İz Kimliği ve Yayılma Kimliği olan bir Span oluşturmanız gerekir. OpenTelemetry bu uygulama için kullanışlı bir kitaplık sağlar. Araç HTTP istemcisine ekstra yeni paketler ekleyin.

step0/src/loadgen/main.go

import (
        "context"
        "encoding/json"
        "fmt"
        "io"
        "log"
        "math/rand"
        "net/http"
        "net/http/httptrace" // step1. add packages
        "net/url"
        "time"
        // step1. add packages
        "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace"
        "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
        // step1. end add packages
        "go.opentelemetry.io/otel"
        "go.opentelemetry.io/otel/attribute"
        stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
        "go.opentelemetry.io/otel/propagation"
        sdktrace "go.opentelemetry.io/otel/sdk/trace"
        semconv "go.opentelemetry.io/otel/semconv/v1.10.0"
        "go.opentelemetry.io/otel/trace"
)

Yük oluşturucu, runQuery işlevindeki net/http ile HTTP'de istemci hizmetini çağırdığından, net/http için yardımcı paketini kullanırız ve httptrace ile otelhttp paketinin uzantısıyla araçları etkinleştiririz.

Öncelikle, kullanılan istemci aracılığıyla HTTP isteklerini çağırmak için httpClient paket genel değişkeni ekleyin.

step0/src/loadgen/main.go

var httpClient = http.Client{
        Transport: otelhttp.NewTransport(http.DefaultTransport)
}

Ardından, OpenTelemetry ve özel HTTP istemcisinden otomatik olarak oluşturulan aralığı kullanarak özel aralığı oluşturmak için runQuery işlevine enstrümantasyon ekleyin. Yapmanız gerekenler:

  1. otel.Tracer() ile global TracerProvider sağlayıcısından bir Tracer alın
  2. Tracer.Start() yöntemiyle kök aralığı oluşturma
  3. Kök aralığını rastgele bir zamanlamada sonlandırın (bu örnekte runQuery işlevinin sonu)

step0/src/loadgen/main.go

        reqURL.RawQuery = v.Encode()
        // step1. replace http.Get() with custom client call
        // resp, err := http.Get(reqURL.String())

        // step1. instrument trace
        ctx := context.Background()
        tr := otel.Tracer("loadgen")
        ctx, span := tr.Start(ctx, "query.request", trace.WithAttributes(
                semconv.TelemetrySDKLanguageGo,
                semconv.ServiceNameKey.String("loadgen.runQuery"),
                attribute.Key("query").String(s),
        ))
        defer span.End()
        ctx = httptrace.WithClientTrace(ctx, otelhttptrace.NewClientTrace(ctx))
        req, err := http.NewRequestWithContext(ctx, "GET", reqURL.String(), nil)
        if err != nil {
                return -1, fmt.Errorf("error creating HTTP request object: %v", err)
        }
        resp, err := httpClient.Do(req)
        // step1. end instrumentation
        if err != nil {
                return -1, fmt.Errorf("error sending request to %v: %v", reqURL.String(), err)
        }

Artık loadgen'deki (HTTP istemci uygulaması) araçları tamamlamış oldunuz. Lütfen go.mod ve go.sum komutlarınızı go mod komutuyla güncellediğinizden emin olun.

go mod tidy

Araç müşteri hizmetleri

Önceki bölümde, aşağıdaki çizimde kırmızı dikdörtgen içine alınan parçaya enstrümantasyon yöntemini uyguladık. Aralık bilgilerini yük oluşturma aracı hizmetinde kullandık. Yük oluşturma hizmetine benzer şekilde, şimdi istemci hizmetinde de enstrümantasyon yapmamız gerekir. Yük oluşturma hizmeti ile farkı, istemci hizmetinin, HTTP üstbilgisindeki yük oluşturucu hizmetinden yayılan İz Kimliği bilgilerini ayıklaması ve bu bilgiyi Aralıkları oluşturmak için kullanmasıdır.

bcaccd06691269f8.png

Cloud Shell Düzenleyici'yi açın ve yük oluşturma aracı hizmeti için yaptığımız gibi gerekli paketleri ekleyin.

step0/src/client/main.go

import (
        "context"
        "encoding/json"
        "fmt"
        "io"
        "log"
        "net/http"
        "net/url"
        "os"
        "time"

        "opentelemetry-trace-codelab-go/client/shakesapp"
        // step1. add new import
        "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
        "go.opentelemetry.io/otel"
        "go.opentelemetry.io/otel/attribute"
        stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
        "go.opentelemetry.io/otel/propagation"
        sdktrace "go.opentelemetry.io/otel/sdk/trace"
        "go.opentelemetry.io/otel/trace"
        "google.golang.org/grpc"
        "google.golang.org/grpc/credentials/insecure"
        // step1. end new import
)

Tekrar, OpenTelemtry'yi kurmamız gerekir. initTracer işlevini loadgen'den kopyalayıp istemci hizmetinin main işlevinde de çağırmanız yeterlidir.

step0/src/client/main.go

// step1. add OpenTelemetry initialization function
func initTracer() (*sdktrace.TracerProvider, error) {
        // create a stdout exporter to show collected spans out to stdout.
        exporter, err := stdout.New(stdout.WithPrettyPrint())
        if err != nil {
                return nil, err
        }

        // for the demonstration, we use AlwaysSmaple sampler to take all spans.
        // do not use this option in production.
        tp := sdktrace.NewTracerProvider(
                sdktrace.WithSampler(sdktrace.AlwaysSample()),
                sdktrace.WithBatcher(exporter),
        )
        otel.SetTracerProvider(tp)
        otel.SetTextMapPropagator(propagation.TraceContext{})
        return tp, nil
}

Şimdi enstrümanları kullanma zamanı. İstemci hizmetinin loadgen hizmetinden gelen HTTP isteklerini kabul etmesi gerektiğinden, işleyiciyi izlemesi gerekir. İstemci hizmetindeki HTTP sunucusu net/http ile uygulanır ve otelhttp paketini yükleyicide yaptığımız gibi kullanabilirsiniz.

Öncelikle işleyici kaydını otelhttp İşleyicisi ile değiştiririz. main işlevinde, HTTP işleyicinin http.HandleFunc() ile kaydedildiği satırları bulun.

step0/src/client/main.go

        // step1. change handler to intercept OpenTelemetry related headers
        // http.HandleFunc("/", svc.handler)
        otelHandler := otelhttp.NewHandler(http.HandlerFunc(svc.handler), "client.handler")
        http.Handle("/", otelHandler)
        // step1. end intercepter setting
        http.HandleFunc("/_genki", svc.health)

Daha sonra, gerçek aralığı işleyicinin içinde ölçeriz. Func (*clientService) işleyici() işleyicisini bulun ve trace.SpanFromContext() ile aralık enstrümantasyonu ekleyin.

step0/src/client/main.go

func (cs *clientService) handler(w http.ResponseWriter, r *http.Request) {
        ...
        ctx := r.Context()
        ctx, cancel := context.WithCancel(ctx)
        defer cancel()
        // step1. instrument trace
        span := trace.SpanFromContext(ctx)
        defer span.End()
        // step1. end instrument
        ...

Bu araçla, handler yönteminin başlangıcından sonuna kadar olan aralıkları elde edersiniz. Aralıkların analiz edilmesini kolaylaştırmak için, eşleşen sayısını sorguya depolayan ekstra bir özellik ekleyin. Günlük satırının hemen önüne aşağıdaki kodu ekleyin.

step0/src/client/main.go

func (cs *clientService) handler(w http.ResponseWriter, r *http.Request) {
        ...
        // step1. add span specific attribute
        span.SetAttributes(attribute.Key("matched").Int64(resp.MatchCount))
        // step1. end adding attribute
        log.Println(string(ret))
        ...

Yukarıdaki tüm araçları kullanarak loadgen ile istemci arasındaki izleme enstrümantasyonunu tamamladınız. Şimdi, bunun işleyiş şekline bakalım. Kodu skaffold ile tekrar çalıştırın.

skaffold dev

Hizmetleri GKE kümesinde çalıştırdıktan bir süre sonra, aşağıdaki gibi çok sayıda günlük mesajı göreceksiniz:

Komut çıkışı

[loadgen] {
[loadgen]       "Name": "query.request",
[loadgen]       "SpanContext": {
[loadgen]               "TraceID": "cfa22247a542beeb55a3434392d46b89",
[loadgen]               "SpanID": "18b06404b10c418b",
[loadgen]               "TraceFlags": "01",
[loadgen]               "TraceState": "",
[loadgen]               "Remote": false
[loadgen]       },
[loadgen]       "Parent": {
[loadgen]               "TraceID": "00000000000000000000000000000000",
[loadgen]               "SpanID": "0000000000000000",
[loadgen]               "TraceFlags": "00",
[loadgen]               "TraceState": "",
[loadgen]               "Remote": false
[loadgen]       },
[loadgen]       "SpanKind": 1,
[loadgen]       "StartTime": "2022-07-14T13:13:36.686751087Z",
[loadgen]       "EndTime": "2022-07-14T13:14:31.849601964Z",
[loadgen]       "Attributes": [
[loadgen]               {
[loadgen]                       "Key": "telemetry.sdk.language",
[loadgen]                       "Value": {
[loadgen]                               "Type": "STRING",
[loadgen]                               "Value": "go"
[loadgen]                       }
[loadgen]               },
[loadgen]               {
[loadgen]                       "Key": "service.name",
[loadgen]                       "Value": {
[loadgen]                               "Type": "STRING",
[loadgen]                               "Value": "loadgen.runQuery"
[loadgen]                       }
[loadgen]               },
[loadgen]               {
[loadgen]                       "Key": "query",
[loadgen]                       "Value": {
[loadgen]                               "Type": "STRING",
[loadgen]                               "Value": "faith"
[loadgen]                       }
[loadgen]               }
[loadgen]       ],
[loadgen]       "Events": null,
[loadgen]       "Links": null,
[loadgen]       "Status": {
[loadgen]               "Code": "Unset",
[loadgen]               "Description": ""
[loadgen]       },
[loadgen]       "DroppedAttributes": 0,
[loadgen]       "DroppedEvents": 0,
[loadgen]       "DroppedLinks": 0,
[loadgen]       "ChildSpanCount": 5,
[loadgen]       "Resource": [
[loadgen]               {
[loadgen]                       "Key": "service.name",
[loadgen]                       "Value": {
[loadgen]                               "Type": "STRING",
[loadgen]                               "Value": "unknown_service:loadgen"
...

stdout dışa aktarıcısı bu mesajları yayar. Loadgen'e göre tüm aralıkların üst öğeleri için TraceID: 00000000000000000000000000000000 olduğunu fark edersiniz. Bunun nedeni, kök aralığı, yani izdeki ilk aralık olması nedeniyle bu aralıktır. Ayrıca "query" yerleştirme özelliğinin, istemci hizmetine iletilen sorgu dizesine sahip olduğunu gördünüz.

Özet

Bu adımda, HTTP'de iletişim kuran yük oluşturma aracı hizmeti ve istemci hizmetiniz var. Bağlamı başarılı bir şekilde hizmetler arasında yayabildiğinizi ve Span bilgilerini her iki hizmetten stdout'a aktarabildiğinizi onayladınız.

Sonraki bölüm

Sonraki adımda gRPC aracılığıyla Bağlam İzlemenin nasıl yayılacağını doğrulamak için istemci hizmeti ve sunucu hizmetini kullanacaksınız.

5. gRPC için Enstrümantasyon

Önceki adımda, isteğin ilk yarısını bu mikro hizmetlerde ayarladık. Bu adımda istemci hizmeti ile sunucu hizmeti arasında gRPC iletişimini sağlamaya çalışırız. (Aşağıdaki resimde yeşil ve mor dikdörtgen)

75310d8e0e3b1a30.png

gRPC istemcisi için önceden derleme aracı

OpenTelemetry'nin ekosistemi, geliştiricilerin uygulamaları kullanmasına yardımcı olan birçok kullanışlı kitaplık sunar. Önceki adımda, net/http paketi için önceden derleme araçları kullandık. Bu adımda, gRPC aracılığıyla Trace Bağlamı yayılmaya çalışırken bunun için kitaplığı kullanacağız.

Önce, otelgrpc adlı önceden oluşturulmuş gRPC paketini içe aktarırsınız.

step0/src/client/main.go

import (
        "context"
        "encoding/json"
        "fmt"
        "io"
        "log"
        "net/http"
        "net/url"
        "os"
        "time"

        "opentelemetry-trace-codelab-go/client/shakesapp"
        // step2. add prebuilt gRPC package (otelgrpc) 
        "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
        "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
        "go.opentelemetry.io/otel"
        "go.opentelemetry.io/otel/attribute"
        stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
        "go.opentelemetry.io/otel/propagation"
        sdktrace "go.opentelemetry.io/otel/sdk/trace"
        "go.opentelemetry.io/otel/trace"
        "google.golang.org/grpc"
        "google.golang.org/grpc/credentials/insecure"
)

Bu kez istemci hizmeti, sunucu hizmetine karşı bir gRPC istemcisi olduğundan gRPC istemcisinde enstrümantasyon yapmanız gerekir. mustConnGRPC işlevini bulun ve istemcinin sunucuya her istek gönderdiğinde yeni aralıklar belirleyen gRPC önleyicilerini ekleyin.

step0/src/client/main.go

// Helper function for gRPC connections: Dial and create client once, reuse.
func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr string) {
        var err error
        // step2. add gRPC interceptor
        interceptorOpt := otelgrpc.WithTracerProvider(otel.GetTracerProvider())
        *conn, err = grpc.DialContext(ctx, addr,
                grpc.WithTransportCredentials(insecure.NewCredentials()),
                grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor(interceptorOpt)),
                grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor(interceptorOpt)),
                grpc.WithTimeout(time.Second*3),
        )
        // step2: end adding interceptor
        if err != nil {
                panic(fmt.Sprintf("Error %s grpc: failed to connect %s", err, addr))
        }
}

Önceki bölümde OpenTelemetry'yi zaten ayarladığınızdan bunu yapmanıza gerek yoktur.

gRPC sunucusu için önceden oluşturulmuş araçlar

gRPC istemcisi için yaptığımız gibi, biz de gRPC sunucusu için önceden oluşturulmuş araç diyoruz. İçe aktarma bölümüne yeni paket ekleyin. Örneğin:

step0/src/server/main.go

import (
        "context"
        "fmt"
        "io/ioutil"
        "log"
        "net"
        "os"
        "regexp"
        "strings"

        "opentelemetry-trace-codelab-go/server/shakesapp"

        "cloud.google.com/go/storage"
        // step2. add OpenTelemetry packages including otelgrpc
        "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
        "go.opentelemetry.io/otel"
        stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
        "go.opentelemetry.io/otel/propagation"
        sdktrace "go.opentelemetry.io/otel/sdk/trace"
        "google.golang.org/api/iterator"
        "google.golang.org/api/option"
        "google.golang.org/grpc"
        healthpb "google.golang.org/grpc/health/grpc_health_v1"
)

Bu, araç sunucusuna ilk kez giriliyor. Bu nedenle, loadgen ve istemci hizmetlerinde yaptığımıza benzer şekilde, önce OpenTelemetry'yi kurmanız gerekir.

step0/src/server/main.go

// step2. add OpenTelemetry initialization function
func initTracer() (*sdktrace.TracerProvider, error) {
        // create a stdout exporter to show collected spans out to stdout.
        exporter, err := stdout.New(stdout.WithPrettyPrint())
        if err != nil {
                return nil, err
        }
        // for the demonstration, we use AlwaysSmaple sampler to take all spans.
        // do not use this option in production.
        tp := sdktrace.NewTracerProvider(
                sdktrace.WithSampler(sdktrace.AlwaysSample()),
                sdktrace.WithBatcher(exporter),
        )
        otel.SetTracerProvider(tp)
        otel.SetTextMapPropagator(propagation.TraceContext{})
        return tp, nil
}

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

Son olarak, sunucu önleyicilerini eklemeniz gerekir. main işlevinde, grpc.NewServer() işlevinin çağrıldığı yeri bulun ve işleve önleyiciler ekleyin.

step0/src/server/main.go

func main() {
        ...
        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)
        ...

Mikro hizmeti çalıştırıp izini onaylayın

Ardından, değiştirdiğiniz kodu skaffold komutuyla çalıştırın.

skaffold dev

Şimdi tekrar, stdout ile ilgili bir dizi span bilgisi görüyorsunuz.

Komut çıkışı

...
[server] {
[server]        "Name": "shakesapp.ShakespeareService/GetMatchCount",
[server]        "SpanContext": {
[server]                "TraceID": "89b472f213a400cf975e0a0041649667",
[server]                "SpanID": "96030dbad0061b3f",
[server]                "TraceFlags": "01",
[server]                "TraceState": "",
[server]                "Remote": false
[server]        },
[server]        "Parent": {
[server]                "TraceID": "89b472f213a400cf975e0a0041649667",
[server]                "SpanID": "cd90cc3859b73890",
[server]                "TraceFlags": "01",
[server]                "TraceState": "",
[server]                "Remote": true
[server]        },
[server]        "SpanKind": 2,
[server]        "StartTime": "2022-07-14T14:05:55.74822525Z",
[server]        "EndTime": "2022-07-14T14:06:03.449258891Z",
[server]        "Attributes": [
...
[server]        ],
[server]        "Events": [
[server]                {
[server]                        "Name": "message",
[server]                        "Attributes": [
...
[server]                        ],
[server]                        "DroppedAttributeCount": 0,
[server]                        "Time": "2022-07-14T14:05:55.748235489Z"
[server]                },
[server]                {
[server]                        "Name": "message",
[server]                        "Attributes": [
...
[server]                        ],
[server]                        "DroppedAttributeCount": 0,
[server]                        "Time": "2022-07-14T14:06:03.449255889Z"
[server]                }
[server]        ],
[server]        "Links": null,
[server]        "Status": {
[server]                "Code": "Unset",
[server]                "Description": ""
[server]        },
[server]        "DroppedAttributes": 0,
[server]        "DroppedEvents": 0,
[server]        "DroppedLinks": 0,
[server]        "ChildSpanCount": 0,
[server]        "Resource": [
[server]                {
...
[server]        ],
[server]        "InstrumentationLibrary": {
[server]                "Name": "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc",
[server]                "Version": "semver:0.33.0",
[server]                "SchemaURL": ""
[server]        }
[server] }
...

Aralık adı yerleştirmediğinizi ve trace.Start() ya da span.SpanFromContext() ile manuel olarak kapsam oluşturmadığınızı fark ettiniz. gRPC önleyicileri bunları oluşturduğu için yine de çok sayıda aralık elde edersiniz.

Özet

Bu adımda OpenTelemetry ekosistem kitaplıklarının desteğiyle gRPC tabanlı iletişimi geliştirdiniz.

Sonraki bölüm

Sonraki adımda, son olarak Cloud Trace ile izi görselleştirecek ve toplanan aralıkları nasıl analiz edeceğinizi öğreneceksiniz.

6. Cloud Trace ile izi görselleştirme

OpenTelemetry ile tüm sistemde enstrümantasyonlu izler kullandınız. Şu ana kadar HTTP ve gRPC hizmetlerinin nasıl kullanılacağını öğrendiniz. Bunları nasıl kullanacağınızı öğrendiniz ancak yine de nasıl analiz edeceğinizi öğrenmediniz. Bu bölümde, stdout dışa aktarıcılarını Cloud Trace dışa aktarıcılarıyla değiştirecek ve izlerinizi nasıl analiz edeceğinizi öğreneceksiniz.

Cloud Trace dışa aktarıcısını kullanma

OpenTelemetry'nin güçlü özelliklerinden biri takılabilirliğidir. Araçlarınız tarafından toplanan tüm aralıkları görselleştirmek için yapmanız gereken, stdout Exporter'ı Cloud Trace aktarıcısıyla değiştirmektir.

Her hizmetin main.go dosyasını açın ve initTracer() işlevini bulun. Satırı silerek stdout dışa aktarıcısı oluşturun ve bunun yerine Cloud Trace dışa aktarıcısı oluşturun.

step0/src/loadgen/main.go

import (
        ...
        // step3. add OpenTelemetry for Cloud Trace package
        cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace"
)

// step1. add OpenTelemetry initialization function
func initTracer() (*sdktrace.TracerProvider, error) {
        // step3. replace stdout exporter with Cloud Trace exporter
        // cloudtrace.New() finds the credentials to Cloud Trace automatically following the
        // rules defined by golang.org/x/oauth2/google.findDefaultCredentailsWithParams.
        // https://pkg.go.dev/golang.org/x/oauth2/google#FindDefaultCredentialsWithParams
        exporter, err := cloudtrace.New()
        // step3. end replacing exporter
        if err != nil {
                return nil, err
        }

        // for the demonstration, we use AlwaysSmaple sampler to take all spans.
        // do not use this option in production.
        tp := sdktrace.NewTracerProvider(
                sdktrace.WithSampler(sdktrace.AlwaysSample()),
                sdktrace.WithBatcher(exporter),
        )
        otel.SetTracerProvider(tp)
        otel.SetTextMapPropagator(propagation.TraceContext{})
        return tp, nil
}

Bu işlevi istemci ve sunucu hizmetinde de düzenlemeniz gerekir.

Mikro hizmeti çalıştırıp izini onaylayın

Düzenlemeden sonra kümeyi skaffold komutuyla normal şekilde çalıştırın.

skaffold dev

Bu durumda, dışa aktarıcıyı Cloud Trace One ile değiştirdiğinizden stdout'ta yapılandırılmış günlükler biçiminde çok fazla aralık bilgisi görmezsiniz.

Komut çıkışı

[loadgen] 2022/07/14 15:01:07 simulated 20 requests
[loadgen] 2022/07/14 15:01:07 simulating client requests, round 37
[loadgen] 2022/07/14 15:01:14 query 'sweet': matched 958
[client] 2022/07/14 15:01:14 {"match_count":958}
[client] 2022/07/14 15:01:14 {"match_count":3040}
[loadgen] 2022/07/14 15:01:14 query 'love': matched 3040
[client] 2022/07/14 15:01:15 {"match_count":349}
[loadgen] 2022/07/14 15:01:15 query 'hello': matched 349
[client] 2022/07/14 15:01:15 {"match_count":484}
[loadgen] 2022/07/14 15:01:15 query 'faith': matched 484
[loadgen] 2022/07/14 15:01:15 query 'insolence': matched 14
[client] 2022/07/14 15:01:15 {"match_count":14}
[client] 2022/07/14 15:01:21 {"match_count":484}
[loadgen] 2022/07/14 15:01:21 query 'faith': matched 484
[client] 2022/07/14 15:01:21 {"match_count":728}
[loadgen] 2022/07/14 15:01:21 query 'world': matched 728
[client] 2022/07/14 15:01:22 {"match_count":484}
[loadgen] 2022/07/14 15:01:22 query 'faith': matched 484
[loadgen] 2022/07/14 15:01:22 query 'hello': matched 349
[client] 2022/07/14 15:01:22 {"match_count":349}
[client] 2022/07/14 15:01:23 {"match_count":1036}
[loadgen] 2022/07/14 15:01:23 query 'friend': matched 1036
[loadgen] 2022/07/14 15:01:28 query 'tear': matched 463
...

Şimdi de tüm aralıkların Cloud Trace'e doğru şekilde gönderilip gönderilmediğini onaylayalım. Cloud Console'a erişip "İz listesi"ne gidin. Bu özelliğe arama kutusundan kolayca erişebilirsiniz. Aksi takdirde, sol bölmedeki menüyü tıklayabilirsiniz. 8b3f8411bd737e06.png.

Sonra, gecikme grafiğinde çok sayıda mavi noktanın dağılımını görüyorsunuz. Her nokta tek bir izi temsil eder.

3ecf131423fc4c40.png

Bunlardan birini tıkladığınızda iz içindeki ayrıntıları görebilirsiniz. 4fd10960c6648a03.png.

Bu basit hızlı bakışta bile birçok bilgiyi zaten biliyorsunuz. Örneğin, şelale grafiğinden, gecikmenin çoğunlukla shakesapp.ShakespeareService/GetMatchCount adlı aralıktan kaynaklandığını görebilirsiniz. (Yukarıdaki resimde 1'e bakın) Bunu özet tablosundan doğrulayabilirsiniz. (En sağdaki sütun, her aralığın süresini gösterir.) Ayrıca bu iz, "arkadaş" sorgusu içindi. (Yukarıdaki resimde 2. öğeye bakın.)

Bu kısa analizler ışığında, GetMatchCount yönteminde daha ayrıntılı aralıkları bilmeniz gerektiğini fark edebilirsiniz. Stdout bilgilerine kıyasla görselleştirme güçlüdür. Cloud Trace ayrıntıları hakkında daha fazla bilgi edinmek için lütfen resmi belgelerimizi inceleyin.

Özet

Bu adımda, stdout dışa aktarıcısını Cloud Trace One ile ve Cloud Trace'te görselleştirilmiş izlerle değiştirdiniz. Ayrıca izleri analiz etmeye nasıl başlayacağınızı da öğrendiniz.

Sonraki bölüm

Sonraki adımda, GetMatchCount'a bir alt kapsam eklemek için sunucu hizmetinin kaynak kodunu değiştireceksiniz.

7. Daha iyi analiz için alt aralık ekleyin

Bir önceki adımda, loadgen'de gözlemlenen gidiş dönüş süresinin nedeninin, çoğunlukla sunucu hizmetindeki gRPC işleyici olan GetMatchCount yöntemindeki süreç olduğunu gördünüz. Ancak işleyici dışında herhangi bir araç kullanmadığımız için şelale grafiğinden daha fazla bilgi elde edemiyoruz. Bu, mikro hizmetler için enstrümantasyona başladığımız yaygın bir durumdur.

3b63a1e471dddb8c.png

Bu bölümde, sunucunun Google Cloud Storage'ı çağırdığı bir alt alanı ayarlayacağız. Bunun nedeni, bazı harici ağ G/Ç'lerinin sürecin uzun sürdüğü ve bunun nedeninin çağrı olup olmadığının belirlenmesidir.

Sunucuda bir alt aralık kullanma

Sunucuda main.go öğesini açın ve readFiles işlevini bulun. Bu işlev, Shakespeare eserlerinin tüm metin dosyalarını getirmek için Google Cloud Storage'a istek çağırıyor. Bu işlevde, istemci hizmetinde HTTP sunucu enstrümantasyonu için yaptığınız gibi bir alt aralık oluşturabilirsiniz.

step0/src/server/main.go

func readFiles(ctx context.Context, bucketName, prefix string) ([]string, error) {
        type resp struct {
                s   string
                err error
        }

        // step4: add an extra span
        span := trace.SpanFromContext(ctx)
        span.SetName("server.readFiles")
        span.SetAttributes(attribute.Key("bucketname").String(bucketName))
        defer span.End()
        // step4: end add span
        ...

Yeni bir kapsam eklemek için hepsi bu. Uygulamayı çalıştırarak bunun nasıl gittiğine bakalım.

Mikro hizmeti çalıştırıp izini onaylayın

Düzenlemeden sonra kümeyi skaffold komutuyla normal şekilde çalıştırın.

skaffold dev

Ayrıca iz listesinden query.request adlı bir iz seçin. shakesapp.ShakespeareService/GetMatchCount altındaki yeni aralık haricinde benzer bir iz şelale grafiği göreceksiniz. (Aşağıda kırmızı bir dikdörtgenle çevrili aralık)

3d4a891aa30d7a32.png

Bu grafikten, Google Cloud Storage'a yapılan harici çağrının büyük miktarda gecikme yaşamasına rağmen gecikmenin büyük kısmını oluşturan başka unsurlar olduğunu söyleyebilirsiniz.

Sadece iz şelale grafiğindeki birkaç bakış açısıyla birçok bilgi edindiniz. Başvurunuzdaki performansla ilgili diğer ayrıntıları nasıl edinebilirsiniz? Profil oluşturucu devreye girer ancak şimdilik bu codelab'in sonunu getirelim ve tüm profil oluşturucu eğiticilerini 2. bölüme ayıralım.

Özet

Bu adımda, sunucu hizmetinde başka bir aralığı uyguladınız ve sistem gecikmesiyle ilgili daha ayrıntılı analizler elde ettiniz.

8. Tebrikler

OpenTelemery ile dağıtılmış izleri başarıyla oluşturdunuz ve Google Cloud Trace'te mikro hizmetteki istek gecikmelerini onayladınız.

Genişletilmiş egzersizler için aşağıdaki konuları kendiniz deneyebilirsiniz.

  • Mevcut uygulama, durum denetimi tarafından oluşturulan tüm aralıkları gönderir. (grpc.health.v1.Health/Check) Bu aralıkları Cloud Traces'te nasıl filtrelersiniz? İpucuna buradan ulaşabilirsiniz.
  • Olay günlüklerini aralıklarla ilişkilendirin ve Google Cloud Trace ve Google Cloud Logging'de nasıl çalıştığını öğrenin. İpucuna buradan ulaşabilirsiniz.
  • Bazı hizmetleri başka bir dildeki bir hizmetle değiştirin ve söz konusu dil için OpenTelemetry ile enstrümantasyon yöntemini kullanmayı deneyin.

Ayrıca, bundan sonra profil oluşturucu hakkında daha fazla bilgi edinmek isterseniz lütfen 2. bölüme geçin. Bu durumda, aşağıdaki temizleme bölümünü atlayabilirsiniz.

Temizleme

Bu codelab'den sonra Google Kubernetes Engine, Google Cloud Trace ve Google Artifact Registry'de beklenmedik ücretlerle karşılaşmamak için lütfen Kubernetes kümesini durdurun ve projeyi sildiğinizden emin olun.

İlk olarak kümeyi silin. Kümeyi skaffold dev ile çalıştırıyorsanız Ctrl-C tuşlarına basmanız yeterlidir. Kümeyi skaffold run ile çalıştırıyorsanız aşağıdaki komutu çalıştırın:

skaffold delete

Komut çıkışı

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

Kümeyi sildikten sonra menü bölmesinden "IAM ve Yönetici" &gt; "Ayarlar"ı, ardından "KAPALI"yı tıklayın. düğmesini tıklayın.

45aa37b7d5e1ddd1.png

Ardından iletişim kutusundaki forma Proje Kimliği'ni (Proje Adı'nı değil) girin ve kapatmayı onaylayın.