เครื่องมือสำหรับเพิ่มประสิทธิภาพของแอปใน Go (ตอนที่ 1: การติดตาม)

1. บทนำ

505827108874614d.png

อัปเดตล่าสุด: 15-07-2022

ความสามารถในการสังเกตการณ์แอปพลิเคชัน

ความสามารถในการสังเกตการณ์และ OpenTelemetry

การสังเกตการณ์เป็นคําที่ใช้อธิบายแอตทริบิวต์ของระบบ ระบบที่มีการสังเกตการณ์ช่วยให้ทีมแก้ไขข้อบกพร่องของระบบได้อย่างต่อเนื่อง ในบริบทนี้ เสาหลัก 3 ประการของความสามารถในการสังเกตการณ์ ได้แก่ บันทึก เมตริก และร่องรอย เป็นเครื่องวัดพื้นฐานสําหรับให้ระบบมีความสามารถในการสังเกตการณ์

OpenTelemetry คือชุดข้อกำหนด ไลบรารี และตัวแทนที่เร่งความเร็วของเครื่องมือวัดและการส่งออกข้อมูลการวัด (บันทึก เมตริก และร่องรอย) ที่ความสามารถในการสังเกตการณ์จําเป็นต้องใช้ OpenTelemetry เป็นมาตรฐานแบบเปิดและโปรเจ็กต์ที่ขับเคลื่อนโดยชุมชนภายใต้ CNCF การใช้ไลบรารีที่โปรเจ็กต์และระบบนิเวศของโปรเจ็กต์มีให้จะช่วยให้นักพัฒนาแอปพลิเคชันสามารถวัดผลแอปพลิเคชันของตนในลักษณะที่เป็นกลางต่อผู้ให้บริการและกับสถาปัตยกรรมหลายแบบ

นอกจากนี้ นอกเหนือจากเสาหลัก 3 ประการของความสามารถในการสังเกตการณ์แล้ว การสร้างโปรไฟล์อย่างต่อเนื่องยังเป็นองค์ประกอบหลักอีกอย่างหนึ่งของความสามารถในการสังเกตการณ์ และขยายฐานผู้ใช้ในอุตสาหกรรมด้วย Cloud Profiler เป็นหนึ่งในเครื่องมือสําคัญและให้บริการอินเทอร์เฟซที่ใช้งานง่ายในการเจาะลึกเมตริกประสิทธิภาพในกองคําเรียกแอปพลิเคชัน

โค้ดแล็บนี้เป็นส่วนหนึ่งของชุดที่ 1 ซึ่งครอบคลุมเครื่องมือวัดร่องรอยแบบกระจายในไมโครเซอร์วิสด้วย OpenTelemetry และ Cloud Trace ส่วนที่ 2 จะกล่าวถึงการสร้างโปรไฟล์อย่างต่อเนื่องด้วย Cloud Profiler

การติดตามแบบกระจาย

ในการติดตาม บันทึก เมตริก และการติดตาม ข้อมูลการติดตามเป็นข้อมูลการวัดผลที่บอกเวลาในการตอบสนองของส่วนใดส่วนหนึ่งของกระบวนการในระบบ โดยเฉพาะอย่างยิ่งในยุคของไมโครเซอร์วิส การติดตามแบบกระจายเป็นปัจจัยที่กระตุ้นให้ค้นหาปัญหาคอขวดด้านเวลาในการตอบสนองในระบบแบบกระจายโดยรวม

เมื่อวิเคราะห์การติดตามแบบกระจาย การแสดงภาพข้อมูลการติดตามเป็นกุญแจสำคัญในการจับภาพเวลาในการตอบสนองโดยรวมของระบบได้อย่างรวดเร็ว ในการติดตามแบบกระจาย เราจะจัดการชุดการเรียกให้ประมวลผลคําขอเดียวไปยังจุดแรกเข้าของระบบในรูปแบบการติดตามที่มีหลายช่วง

ช่วงเวลาแสดงถึงหน่วยงานแต่ละหน่วยที่ทําในระบบแบบกระจาย โดยบันทึกเวลาเริ่มต้นและเวลาสิ้นสุด โดยทั่วไปแล้ว แต่ละช่วงมักจะมีความสัมพันธ์แบบลําดับชั้นต่อกัน ในภาพด้านล่าง ช่วงขนาดเล็กทั้งหมดเป็นช่วงย่อยของช่วง /messages ขนาดใหญ่ และประกอบกันเป็นการติดตามรายการเดียวซึ่งแสดงเส้นทางของงานในระบบ

การติดตาม

Google Cloud Trace เป็นหนึ่งในตัวเลือกสําหรับแบ็กเอนด์การติดตามแบบกระจาย และผสานรวมกับผลิตภัณฑ์อื่นๆ ใน Google Cloud ได้อย่างดี

สิ่งที่คุณจะสร้าง

ในโค้ดแล็บนี้ คุณจะได้ติดตั้งเครื่องมือติดตามข้อมูลในบริการที่เรียกว่า "แอปพลิเคชัน Shakespeare" (หรือที่เรียกว่า Shakesapp) ที่ทำงานบนคลัสเตอร์ Google Kubernetes Engine สถาปัตยกรรมของ Shakesapp มีดังนี้

44e243182ced442f.png

  • Loadgen ส่งสตริงการค้นหาไปยังไคลเอ็นต์ใน HTTP
  • ไคลเอ็นต์ส่งคําค้นหาจาก Loadgen ไปยังเซิร์ฟเวอร์ใน gRPC
  • เซิร์ฟเวอร์ยอมรับการค้นหาจากไคลเอ็นต์ ดึงข้อมูลผลงานทั้งหมดของ Shakespeare ในรูปแบบข้อความจาก Google Cloud Storage ค้นหาบรรทัดที่มีคําค้นหา และแสดงจํานวนบรรทัดที่ตรงกับไคลเอ็นต์

คุณจะเครื่องมือวัดข้อมูลการติดตามในคําขอ หลังจากนั้น ให้ฝังตัวแทนเครื่องมือวิเคราะห์โปรไฟล์ในเซิร์ฟเวอร์และตรวจสอบปัญหาคอขวด

สิ่งที่คุณจะได้เรียนรู้

  • วิธีเริ่มต้นใช้งานไลบรารีการติดตาม OpenTelemetry ในโปรเจ็กต์ Go
  • วิธีสร้างช่วงด้วยไลบรารี
  • วิธีเผยแพร่บริบทของช่วงระหว่างคอมโพเนนต์แอป
  • วิธีส่งข้อมูลการติดตามไปยัง Cloud Trace
  • วิธีวิเคราะห์การติดตามใน Cloud Trace

โค้ดแล็บนี้อธิบายวิธีเครื่องมือวัดผลไมโครเซอร์วิส ตัวอย่างนี้มีเพียง 3 คอมโพเนนต์ (เครื่องมือสร้างโหลด ไคลเอ็นต์ และเซิร์ฟเวอร์) เพื่อให้เข้าใจได้ง่าย แต่คุณใช้กระบวนการเดียวกันที่อธิบายไว้ในโค้ดแล็บนี้กับระบบที่ซับซ้อนและขนาดใหญ่มากขึ้นได้

สิ่งที่ต้องมี

  • ความรู้พื้นฐานเกี่ยวกับ Go
  • ความรู้พื้นฐานเกี่ยวกับ Kubernetes

2. การตั้งค่าและข้อกําหนด

การตั้งค่าสภาพแวดล้อมด้วยตนเอง

หากยังไม่มีบัญชี Google (Gmail หรือ Google Apps) คุณต้องสร้างบัญชี ลงชื่อเข้าใช้คอนโซล Google Cloud Platform ( console.cloud.google.com) และสร้างโปรเจ็กต์ใหม่

หากคุณมีโปรเจ็กต์อยู่แล้ว ให้คลิกเมนูแบบเลื่อนลงเพื่อเลือกโปรเจ็กต์ที่ด้านซ้ายบนของคอนโซล

7a32e5469db69e9.png

และคลิกปุ่ม "โปรเจ็กต์ใหม่" ในกล่องโต้ตอบที่ปรากฏขึ้นเพื่อสร้างโปรเจ็กต์ใหม่

7136b3ee36ebaf89.png

หากยังไม่มีโปรเจ็กต์ คุณควรเห็นกล่องโต้ตอบเช่นนี้เพื่อสร้างโปรเจ็กต์แรก

870a3cbd6541ee86.png

กล่องโต้ตอบการสร้างโปรเจ็กต์ที่ตามมาจะช่วยให้คุณป้อนรายละเอียดของโปรเจ็กต์ใหม่ได้ ดังนี้

affdc444517ba805.png

โปรดจดจำรหัสโปรเจ็กต์ ซึ่งเป็นชื่อที่ไม่ซ้ำกันในโปรเจ็กต์ Google Cloud ทั้งหมด (ชื่อด้านบนมีผู้ใช้แล้วและจะใช้ไม่ได้ ต้องขออภัยด้วย) ซึ่งจะเรียกว่า PROJECT_ID ในภายหลังในโค้ดแล็บนี้

ถัดไป คุณจะต้องเปิดใช้การเรียกเก็บเงินในคอนโซลนักพัฒนาซอฟต์แวร์เพื่อใช้ทรัพยากร Google Cloud และเปิดใช้ Cloud Trace API หากยังไม่ได้ดำเนินการ

15d0ef27a8fbab27.png

ค่าใช้จ่ายในการเรียกใช้ Codelab นี้ไม่ควรเกิน 200 บาท แต่อาจมากกว่านั้นหากคุณตัดสินใจใช้ทรัพยากรเพิ่มเติมหรือปล่อยไว้ให้ทำงาน (ดูส่วน "ล้างข้อมูล" ที่ท้ายเอกสารนี้) ดูราคาของ Google Cloud Trace, Google Kubernetes Engine และ Google Artifact Registry ได้ในเอกสารประกอบอย่างเป็นทางการ

ผู้ใช้ใหม่ของ Google Cloud Platform มีสิทธิ์รับช่วงทดลองใช้ฟรีมูลค่า$300 ซึ่งจะทำให้โค้ดแล็บนี้ไม่มีค่าใช้จ่ายใดๆ ทั้งสิ้น

การตั้งค่า Google Cloud Shell

แม้ว่า Google Cloud และ Google Cloud Trace จะทำงานจากระยะไกลจากแล็ปท็อปได้ แต่ในโค้ดแล็บนี้เราจะใช้ Google Cloud Shell ซึ่งเป็นสภาพแวดล้อมบรรทัดคำสั่งที่ทำงานในระบบคลาวด์

เครื่องเสมือนที่ใช้ Debian นี้จะโหลดเครื่องมือการพัฒนาทั้งหมดที่คุณต้องการ ซึ่งจะมีไดเรกทอรีหลักขนาด 5 GB ถาวรและทำงานใน Google Cloud ซึ่งช่วยเพิ่มประสิทธิภาพเครือข่ายและการรับรองได้อย่างมีประสิทธิภาพ ซึ่งหมายความว่าสิ่งที่คุณต้องใช้สำหรับโค้ดแล็บนี้ก็มีเพียงเบราว์เซอร์ (ใช่ โค้ดแล็บนี้ใช้ได้ใน Chromebook)

หากต้องการเปิดใช้งาน Cloud Shell จาก Cloud Console เพียงคลิกเปิดใช้งาน Cloud Shell gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A (ระบบจะใช้เวลาเพียงไม่กี่นาทีในการเตรียมการและเชื่อมต่อกับสภาพแวดล้อม)

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

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

เมื่อเชื่อมต่อกับ Cloud Shell แล้ว คุณควรจะเห็นการตรวจสอบสิทธิ์แล้วและโปรเจ็กต์ได้รับการตั้งค่าเป็น PROJECT_ID ของคุณแล้ว

gcloud auth list

เอาต์พุตจากคำสั่ง

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

เอาต์พุตจากคำสั่ง

[core]
project = <PROJECT_ID>

หากไม่ได้ตั้งค่าโปรเจ็กต์ไว้ด้วยเหตุผลบางประการ ให้ใช้คําสั่งต่อไปนี้

gcloud config set project <PROJECT_ID>

หากกำลังมองหา PROJECT_ID ตรวจสอบรหัสที่คุณใช้ในขั้นตอนการตั้งค่าหรือค้นหาในแดชบอร์ดของ Cloud Console

158fNPfwSxsFqz9YbtJVZes8viTS3d1bV4CVhij3XPxuzVFOtTObnwsphlm6lYGmgdMFwBJtc-FaLrZU7XHAg_ZYoCrgombMRR3h-eolLPcvO351c5iBv506B3ZwghZoiRg6cz23Qw

นอกจากนี้ Cloud Shell ยังตั้งค่าตัวแปรสภาพแวดล้อมบางอย่างโดยค่าเริ่มต้น ซึ่งอาจมีประโยชน์เมื่อคุณเรียกใช้คำสั่งในอนาคต

echo $GOOGLE_CLOUD_PROJECT

เอาต์พุตจากคำสั่ง

<PROJECT_ID>

สุดท้าย ให้กำหนดโซนและการกำหนดค่าโปรเจ็กต์เริ่มต้น

gcloud config set compute/zone us-central1-f

คุณเลือกโซนต่างๆ ได้ ดูข้อมูลเพิ่มเติมได้ที่ภูมิภาคและโซน

ไปที่การตั้งค่าภาษา

ใน Codelab นี้ เราจะใช้ Go สำหรับซอร์สโค้ดทั้งหมด เรียกใช้คําสั่งต่อไปนี้ใน Cloud Shell และตรวจสอบว่า Go เป็นเวอร์ชัน 1.17 ขึ้นไป

go version

เอาต์พุตจากคำสั่ง

go version go1.18.3 linux/amd64

ตั้งค่าคลัสเตอร์ Google Kubernetes

ในโค้ดแล็บนี้ คุณจะเรียกใช้คลัสเตอร์ของไมโครเซอร์วิสใน Google Kubernetes Engine (GKE) กระบวนการของโค้ดแล็บนี้มีดังนี้

  1. ดาวน์โหลดโปรเจ็กต์พื้นฐานลงใน Cloud Shell
  2. สร้าง Microservice ลงในคอนเทนเนอร์
  3. อัปโหลดคอนเทนเนอร์ไปยัง Google Artifact Registry (GAR)
  4. ทำให้คอนเทนเนอร์ใช้งานได้ใน GKE
  5. แก้ไขซอร์สโค้ดของบริการสําหรับเครื่องมือวัดร่องรอย
  6. ไปที่ขั้นตอนที่ 2

เปิดใช้ Kubernetes Engine

ก่อนอื่นเราต้องตั้งค่าคลัสเตอร์ Kubernetes ที่ Shakesapp ทำงานบน GKE ดังนั้นเราต้องเปิดใช้ GKE ไปที่เมนู "Kubernetes Engine" แล้วกดปุ่มเปิดใช้งาน

548cfd95bc6d344d.png

ตอนนี้คุณก็พร้อมสร้างคลัสเตอร์ Kubernetes แล้ว

สร้างคลัสเตอร์ Kubernetes

ใน Cloud Shell ให้เรียกใช้คําสั่งต่อไปนี้เพื่อสร้างคลัสเตอร์ Kubernetes โปรดตรวจสอบว่าค่าโซนอยู่ภายใต้ภูมิภาคที่คุณจะใช้สำหรับการสร้างที่เก็บข้อมูล Artifact Registry เปลี่ยนค่าโซน us-central1-f หากภูมิภาคของที่เก็บข้อมูลไม่ครอบคลุมโซนนั้น

gcloud container clusters create otel-trace-codelab2 \
--zone us-central1-f \
--release-channel rapid \
--preemptible \
--enable-autoscaling \
--max-nodes 8 \
--no-enable-ip-alias \
--scopes cloud-platform

เอาต์พุตจากคำสั่ง

Note: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s).
Creating cluster otel-trace-codelab2 in us-central1-f... Cluster is being health-checked (master is healthy)...done.     
Created [https://container.googleapis.com/v1/projects/development-215403/zones/us-central1-f/clusters/otel-trace-codelab2].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-f/otel-trace-codelab2?project=development-215403
kubeconfig entry generated for otel-trace-codelab2.
NAME: otel-trace-codelab2
LOCATION: us-central1-f
MASTER_VERSION: 1.23.6-gke.1501
MASTER_IP: 104.154.76.89
MACHINE_TYPE: e2-medium
NODE_VERSION: 1.23.6-gke.1501
NUM_NODES: 3
STATUS: RUNNING

การตั้งค่า Artifact Registry และ skaffold

ตอนนี้เรามีคลัสเตอร์ Kubernetes ที่พร้อมใช้งานแล้ว ขั้นตอนถัดไปคือเตรียม Container Registry เพื่อพุชและติดตั้งใช้งานคอนเทนเนอร์ ในขั้นตอนเหล่านี้ เราต้องตั้งค่า Artifact Registry (GAR) และ skaffold เพื่อใช้งาน

การตั้งค่า Artifact Registry

ไปที่เมนู "Artifact Registry" แล้วกดปุ่มเปิดใช้งาน

45e384b87f7cf0db.png

หลังจากนั้นสักครู่ คุณจะเห็นเบราว์เซอร์ที่เก็บของ GAR คลิกปุ่ม "สร้างที่เก็บข้อมูล" แล้วป้อนชื่อที่เก็บข้อมูล

d6a70f4cb4ebcbe3.png

ในโค้ดแล็บนี้ เราจะตั้งชื่อที่เก็บข้อมูลใหม่ว่า trace-codelab รูปแบบของอาร์ติแฟกต์คือ "Docker" และประเภทตำแหน่งคือ "ภูมิภาค" เลือกภูมิภาคที่อยู่ใกล้กับภูมิภาคที่คุณกำหนดเป็นโซนเริ่มต้นของ Google Compute Engine ตัวอย่างเช่น ในตัวอย่างนี้ เราได้เลือก "us-central1-f" ด้านบน ดังนั้นเราจะเลือก "us-central1 (Iowa)" ที่นี่ จากนั้นคลิกปุ่ม "สร้าง"

9c2d1ce65258ef70.png

ตอนนี้คุณจะเห็น "trace-codelab" ในเบราว์เซอร์ที่เก็บ

7a3c1f47346bea15.png

เราจะกลับมาที่นี่ในภายหลังเพื่อตรวจสอบเส้นทางรีจิสทรี

การตั้งค่า Skaffold

Skaffold เป็นเครื่องมือที่มีประโยชน์เมื่อคุณสร้างไมโครเซอร์วิสที่ทำงานบน Kubernetes ซึ่งจะจัดการเวิร์กโฟลว์ของการสร้าง การพุช และการนำคอนเทนเนอร์ของแอปพลิเคชันไปใช้ด้วยชุดคำสั่งเล็กๆ โดยค่าเริ่มต้น Skaffold จะใช้ Docker Registry เป็นรีจิสทรีคอนเทนเนอร์ คุณจึงต้องกําหนดค่า Skaffold ให้รู้จัก GAR เมื่อมีการพุชคอนเทนเนอร์

เปิด Cloud Shell อีกครั้งและยืนยันว่าได้ติดตั้ง skaffold แล้ว (Cloud Shell จะติดตั้ง skaffold ลงในสภาพแวดล้อมโดยค่าเริ่มต้น) เรียกใช้คำสั่งต่อไปนี้และดูเวอร์ชัน skaffold

skaffold version

เอาต์พุตจากคำสั่ง

v1.38.0

ตอนนี้คุณลงทะเบียนที่เก็บเริ่มต้นสำหรับ skaffold ได้แล้ว หากต้องการดูเส้นทางรีจิสทรี ให้ไปที่แดชบอร์ดรีจิสทรีอาร์ติแฟกต์ แล้วคลิกชื่อที่เก็บข้อมูลที่เพิ่งตั้งค่าไว้ในขั้นตอนก่อนหน้า

7a3c1f47346bea15.png

จากนั้นคุณจะเห็นเส้นทางเบรดครัมบ์ที่ด้านบนของหน้า คลิกไอคอน e157b1359c3edc06.png เพื่อคัดลอกเส้นทางรีจิสทรีไปยังคลิปบอร์ด

e0f2ae2144880b8b.png

เมื่อคลิกปุ่มคัดลอก คุณจะเห็นกล่องโต้ตอบที่ด้านล่างของเบราว์เซอร์พร้อมข้อความดังต่อไปนี้

คัดลอก "us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab" แล้ว

กลับไปที่ Cloud Shell เรียกใช้คําสั่ง skaffold config set default-repo ด้วยค่าที่คุณเพิ่งคัดลอกมาจากหน้าแดชบอร์ด

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

เอาต์พุตจากคำสั่ง

set value default-repo to us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab for context gke_stackdriver-sandbox-3438851889_us-central1-b_stackdriver-sandbox

นอกจากนี้ คุณยังต้องกำหนดค่ารีจิสทรีเป็นการกำหนดค่า Docker ด้วย เรียกใช้คำสั่งต่อไปนี้

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

เอาต์พุตจากคำสั่ง

{
  "credHelpers": {
    "gcr.io": "gcloud",
    "us.gcr.io": "gcloud",
    "eu.gcr.io": "gcloud",
    "asia.gcr.io": "gcloud",
    "staging-k8s.gcr.io": "gcloud",
    "marketplace.gcr.io": "gcloud",
    "us-central1-docker.pkg.dev": "gcloud"
  }
}
Adding credentials for: us-central1-docker.pkg.dev

ตอนนี้คุณพร้อมที่จะไปยังขั้นตอนถัดไปเพื่อตั้งค่าคอนเทนเนอร์ Kubernetes ใน GKE

สรุป

ในขั้นตอนนี้ คุณจะต้องตั้งค่าสภาพแวดล้อมของ Codelab โดยทำดังนี้

  • ตั้งค่า Cloud Shell
  • สร้างที่เก็บ Artifact Registry สำหรับรีจิสทรีคอนเทนเนอร์
  • ตั้งค่า skaffold เพื่อใช้ที่เก็บคอนเทนเนอร์
  • สร้างคลัสเตอร์ Kubernetes ที่ไมโครเซอร์วิสของ Codelab ทำงานอยู่

วิดีโอถัดไป

ในขั้นตอนถัดไป คุณจะต้องสร้าง พุช และติดตั้งใช้งานไมโครเซอร์วิสในคลัสเตอร์

3. สร้าง พุช และทำให้ไมโครเซอร์วิสใช้งานได้

ดาวน์โหลดเนื้อหาใน Codelab

ในขั้นตอนก่อนหน้า เราได้ตั้งค่าข้อกําหนดเบื้องต้นทั้งหมดสําหรับโค้ดแล็บนี้แล้ว ตอนนี้คุณก็พร้อมเรียกใช้ทั้งไมโครเซอร์วิสบนแพลตฟอร์มดังกล่าวแล้ว เนื้อหาของโค้ดแล็บโฮสต์อยู่ใน GitHub ดังนั้นให้ดาวน์โหลดเนื้อหาดังกล่าวลงในสภาพแวดล้อม Cloud Shell ด้วยคำสั่ง git ต่อไปนี้

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

โครงสร้างไดเรกทอรีของโปรเจ็กต์มีดังนี้

.
├── README.md
├── step0
│   ├── manifests
│   ├── proto
│   ├── skaffold.yaml
│   └── src
├── step1
│   ├── manifests
│   ├── proto
│   ├── skaffold.yaml
│   └── src
├── step2
│   ├── manifests
│   ├── proto
│   ├── skaffold.yaml
│   └── src
├── step3
│   ├── manifests
│   ├── proto
│   ├── skaffold.yaml
│   └── src
├── step4
│   ├── manifests
│   ├── proto
│   ├── skaffold.yaml
│   └── src
├── step5
│   ├── manifests
│   ├── proto
│   ├── skaffold.yaml
│   └── src
└── step6
    ├── manifests
    ├── proto
    ├── skaffold.yaml
    └── src
  • manifests: ไฟล์ Manifest ของ Kubernetes
  • proto: คําจํากัดความของ proto สําหรับการสื่อสารระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์
  • src: ไดเรกทอรีสำหรับซอร์สโค้ดของบริการแต่ละรายการ
  • skaffold.yaml: ไฟล์การกําหนดค่าสําหรับ skaffold

ใน Codelab นี้ คุณจะอัปเดตซอร์สโค้ดที่อยู่ในโฟลเดอร์ step0 นอกจากนี้ คุณยังดูคำตอบในซอร์สโค้ดในโฟลเดอร์ step[1-6] ได้โดยทำตามขั้นตอนต่อไปนี้ (ส่วนที่ 1 ครอบคลุมขั้นตอนที่ 0 ถึง 4 และส่วนที่ 2 ครอบคลุมขั้นตอนที่ 5 และ 6)

เรียกใช้คําสั่ง skaffold

สุดท้าย คุณก็พร้อมที่จะสร้าง พุช และติดตั้งใช้งานเนื้อหาทั้งหมดในคลัสเตอร์ Kubernetes ที่เพิ่งสร้างขึ้น ฟังดูแล้วเหมือนจะมีหลายขั้นตอน แต่จริงๆ แล้ว skaffold จะทําทุกอย่างให้คุณ ลองใช้คำสั่งต่อไปนี้

cd step0
skaffold dev

ทันทีที่เรียกใช้คําสั่ง คุณจะเห็นเอาต์พุตบันทึกของ docker build และยืนยันว่ามีการพุชไปยังรีจิสทรีเรียบร้อยแล้ว

เอาต์พุตจากคำสั่ง

...
---> Running in c39b3ea8692b
 ---> 90932a583ab6
Successfully built 90932a583ab6
Successfully tagged us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step1
The push refers to repository [us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice]
cc8f5a05df4a: Preparing
5bf719419ee2: Preparing
2901929ad341: Preparing
88d9943798ba: Preparing
b0fdf826a39a: Preparing
3c9c1e0b1647: Preparing
f3427ce9393d: Preparing
14a1ca976738: Preparing
f3427ce9393d: Waiting
14a1ca976738: Waiting
3c9c1e0b1647: Waiting
b0fdf826a39a: Layer already exists
88d9943798ba: Layer already exists
f3427ce9393d: Layer already exists
3c9c1e0b1647: Layer already exists
14a1ca976738: Layer already exists
2901929ad341: Pushed
5bf719419ee2: Pushed
cc8f5a05df4a: Pushed
step1: digest: sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe size: 2001

หลังจากพุชคอนเทนเนอร์บริการทั้งหมดแล้ว การติดตั้งใช้งาน Kubernetes จะเริ่มขึ้นโดยอัตโนมัติ

เอาต์พุตจากคำสั่ง

sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8 size: 1997
Tags used in deployment:
 - serverservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step4@sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe
 - clientservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/clientservice:step4@sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8
 - loadgen -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/loadgen:step4@sha256:eea2e5bc8463ecf886f958a86906cab896e9e2e380a0eb143deaeaca40f7888a
Starting deploy...
 - deployment.apps/clientservice created
 - service/clientservice created
 - deployment.apps/loadgen created
 - deployment.apps/serverservice created
 - service/serverservice created

หลังจากการทำให้ใช้งานได้แล้ว คุณจะเห็นบันทึกแอปพลิเคชันจริงที่ส่งไปยัง stdout ในคอนเทนเนอร์แต่ละรายการดังต่อไปนี้

เอาต์พุตจากคำสั่ง

[client] 2022/07/14 06:33:15 {"match_count":3040}
[loadgen] 2022/07/14 06:33:15 query 'love': matched 3040
[client] 2022/07/14 06:33:15 {"match_count":3040}
[loadgen] 2022/07/14 06:33:15 query 'love': matched 3040
[client] 2022/07/14 06:33:16 {"match_count":3040}
[loadgen] 2022/07/14 06:33:16 query 'love': matched 3040
[client] 2022/07/14 06:33:19 {"match_count":463}
[loadgen] 2022/07/14 06:33:19 query 'tear': matched 463
[loadgen] 2022/07/14 06:33:20 query 'world': matched 728
[client] 2022/07/14 06:33:20 {"match_count":728}
[client] 2022/07/14 06:33:22 {"match_count":463}
[loadgen] 2022/07/14 06:33:22 query 'tear': matched 463

โปรดทราบว่า ณ จุดนี้ คุณควรเห็นข้อความจากเซิร์ฟเวอร์ โอเค ในที่สุดคุณก็พร้อมที่จะเริ่มเครื่องมือวัดแอปพลิเคชันด้วย OpenTelemetry สําหรับการติดตามแบบกระจายของบริการ

โปรดปิดคลัสเตอร์ด้วย Ctrl-C ก่อนเริ่มเครื่องมือวัดบริการ

เอาต์พุตจากคำสั่ง

...
[client] 2022/07/14 06:34:57 {"match_count":1}
[loadgen] 2022/07/14 06:34:57 query 'what's past is prologue': matched 1
^CCleaning up...
 - W0714 06:34:58.464305   28078 gcp.go:120] WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead.
 - To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke
 - deployment.apps "clientservice" deleted
 - service "clientservice" deleted
 - deployment.apps "loadgen" deleted
 - deployment.apps "serverservice" deleted
 - service "serverservice" deleted

สรุป

ในขั้นตอนนี้ คุณได้เตรียมเนื้อหาของ Codelab ในสภาพแวดล้อมและยืนยันว่า skaffold ทํางานตามที่คาดไว้

วิดีโอถัดไป

ในขั้นตอนถัดไป คุณจะแก้ไขซอร์สโค้ดของบริการ loadgen เพื่อวัดข้อมูลการติดตาม

4. เครื่องมือวัดสำหรับ HTTP

แนวคิดของเครื่องมือวัดและการนำไปใช้ของร่องรอย

ก่อนแก้ไขซอร์สโค้ด เราขออธิบายวิธีการทํางานของร่องรอยแบบกระจายในแผนภาพง่ายๆ สักเล็กน้อย

6be42e353b9bfd1d.png

ในตัวอย่างนี้ เราจะใช้เครื่องมือวัดผลโค้ดเพื่อส่งออกข้อมูลการติดตามและช่วงไปยัง Cloud Trace และเผยแพร่บริบทการติดตามในคําขอจากบริการ loadgen ไปยังบริการเซิร์ฟเวอร์

แอปพลิเคชันต้องส่งข้อมูลเมตาการติดตาม เช่น รหัสการติดตามและรหัสสแปน เพื่อให้การติดตามในระบบคลาวด์รวบรวมสแปนทั้งหมดที่มีรหัสการติดตามเดียวกันเข้าด้วยกันเป็นข้อมูลการติดตามรายการเดียว นอกจากนี้ แอปพลิเคชันยังต้องเผยแพร่บริบทการติดตาม (การรวมรหัสการติดตามและรหัสสแปนของสแปนหลัก) ในบริการดาวน์สตรีมที่ต้องการ เพื่อให้ทราบบริบทการติดตามที่จัดการอยู่

OpenTelemetry ช่วยให้คุณทำสิ่งต่อไปนี้ได้

  • เพื่อสร้างรหัสการติดตามและรหัสช่วงที่ไม่ซ้ำกัน
  • เพื่อส่งออกรหัสการติดตามและรหัส Span ไปยังแบ็กเอนด์
  • เพื่อเผยแพร่บริบทการติดตามไปยังบริการอื่นๆ
  • เพื่อฝังข้อมูลเมตาเพิ่มเติมซึ่งช่วยในการวิเคราะห์ร่องรอย

คอมโพเนนต์ในการติดตาม OpenTelemetry

b01f7bb90188db0d.png

กระบวนการวัดการติดตามแอปพลิเคชันด้วย OpenTelemetry มีดังนี้

  1. สร้างผู้ส่งออก
  2. สร้าง TracerProvider ที่เชื่อมโยงกับตัวส่งออกใน 1 และตั้งค่าเป็นค่าส่วนกลาง
  3. ตั้งค่า TextMapPropagaror เพื่อตั้งค่าวิธีการนำไปใช้
  4. รับ Tracer จาก TracerProvider
  5. สร้าง Span จากเครื่องมือติดตาม

ในตอนนี้ คุณไม่จำเป็นต้องเข้าใจคุณสมบัติโดยละเอียดในแต่ละคอมโพเนนต์ แต่สิ่งที่ควรจำไว้ที่สำคัญที่สุดมีดังนี้

  • ผู้ส่งออกที่นี่สามารถเสียบเข้ากับ TracerProvider
  • TracerProvider จะเก็บการกําหนดค่าทั้งหมดเกี่ยวกับการสุ่มตัวอย่างและการส่งออกการติดตาม
  • ร่องรอยทั้งหมดจะรวมอยู่ในออบเจ็กต์ Tracer

เมื่อเข้าใจแล้ว เรามาเริ่มเขียนโค้ดกัน

ช่วงแรกของเครื่องดนตรี

บริการเครื่องมือสร้างโหลด

เปิดเครื่องมือแก้ไข Cloud Shell โดยกดปุ่ม 776a11bfb2122549.png ที่ด้านขวาบนของ Cloud Shell เปิด step0/src/loadgen/main.go จากโปรแกรมสำรวจในแผงด้านซ้าย แล้วค้นหาฟังก์ชันหลัก

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

ในฟังก์ชันหลัก คุณจะเห็นลูปเรียกใช้ฟังก์ชัน run ในการใช้งานปัจจุบัน ส่วนนี้มีบรรทัดบันทึก 2 บรรทัดซึ่งบันทึกการเริ่มต้นและการสิ้นสุดของการเรียกใช้ฟังก์ชัน ตอนนี้มาติดแท็กข้อมูล Span เพื่อติดตามเวลาในการตอบสนองของการเรียกใช้ฟังก์ชันกัน

ก่อนอื่น ตามที่ระบุไว้ในส่วนก่อนหน้า ให้เราตั้งค่าการกําหนดค่าทั้งหมดสําหรับ OpenTelemetry เพิ่มแพ็กเกจ OpenTelemetry ดังนี้

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
)

เราสร้างฟังก์ชันการตั้งค่าชื่อ initTracer และเรียกใช้ในฟังก์ชัน main เพื่อให้อ่านง่าย

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 เหมือนกับที่อธิบายไว้ในส่วนก่อนหน้า ในการใช้งานนี้ เราใช้เครื่องมือส่งออก stdout ที่ส่งออกข้อมูลการติดตามทั้งหมดไปยัง stdout ในรูปแบบ Structured

จากนั้นเรียกใช้จากฟังก์ชันหลัก เรียกใช้ initTracer() และอย่าลืมเรียกใช้ TracerProvider.Shutdown() เมื่อปิดแอปพลิเคชัน

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

เมื่อตั้งค่าเสร็จแล้ว คุณจะต้องสร้าง Span ที่มีรหัสการติดตามและรหัส Span ที่ไม่ซ้ำกัน OpenTelemetry มีไลบรารีที่มีประโยชน์สำหรับการดำเนินการนี้ เพิ่มแพ็กเกจใหม่เพิ่มเติมลงในไคลเอ็นต์ HTTP ของเครื่องมือ

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

เนื่องจากเครื่องมือสร้างโหลดเรียกบริการไคลเอ็นต์ใน HTTP ด้วย net/http ในฟังก์ชัน runQuery เราจึงใช้แพ็กเกจ contrib สําหรับ net/http และเปิดใช้เครื่องมือวัดผลด้วยส่วนขยายของแพ็กเกจ httptrace และ otelhttp

ก่อนอื่นให้เพิ่มตัวแปร httpClient ระดับแพ็กเกจเพื่อเรียกคําขอ HTTP ผ่านไคลเอ็นต์ที่เครื่องมือวัด

step0/src/loadgen/main.go

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

ถัดไป ให้เพิ่มเครื่องมือวัดผลในฟังก์ชัน runQuery เพื่อสร้างสแปนที่กำหนดเองโดยใช้ OpenTelemetry และสแปนที่สร้างขึ้นโดยอัตโนมัติจากไคลเอ็นต์ HTTP ที่กําหนดเอง สิ่งที่คุณต้องทำมีดังนี้

  1. รับ Tracer จาก TracerProvider ทั่วโลกด้วย otel.Tracer()
  2. สร้างช่วงรูทด้วยเมธอด Tracer.Start()
  3. สิ้นสุดช่วงรูทตามเวลาที่กำหนด (ในกรณีนี้คือสิ้นสุดฟังก์ชัน runQuery)

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

ตอนนี้คุณก็ติดตั้งเครื่องมือวัดใน loadgen (แอปพลิเคชันไคลเอ็นต์ HTTP) เสร็จแล้ว โปรดอัปเดต go.mod และ go.sum ด้วยคำสั่ง go mod

go mod tidy

บริการลูกค้าเกี่ยวกับเครื่องดนตรี

ในส่วนก่อนหน้านี้ เราได้ติดตั้งเครื่องมือวัดในส่วนที่ล้อมรอบด้วยสี่เหลี่ยมผืนผ้าสีแดงในภาพวาดด้านล่าง เราติดตั้งเครื่องมือวัดข้อมูลช่วงในบริการสร้างจํานวนการเรียกใช้ ตอนนี้เราต้องติดตั้งเครื่องมือวัดบริการไคลเอ็นต์ ซึ่งคล้ายกับบริการสร้างโหลด ความแตกต่างจากบริการสร้างโหลดคือบริการไคลเอ็นต์ต้องดึงข้อมูลรหัสการติดตามที่เผยแพร่จากบริการสร้างโหลดในส่วนหัว HTTP และใช้รหัสเพื่อสร้าง Span

bcaccd06691269f8.png

เปิด Cloud Shell Editor และเพิ่มแพ็กเกจที่จำเป็นเช่นเดียวกับที่เราทำกับบริการสร้างจํานวนการเรียกใช้

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
)

เราต้องตั้งค่า OpenTelemtry อีกครั้ง เพียงคัดลอกและวางฟังก์ชัน initTracer จาก loadgen แล้วเรียกใช้ในฟังก์ชัน main ของบริการลูกค้าด้วย

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
}

ตอนนี้ถึงเวลาติดเครื่องมือวัดใน Span เนื่องจากบริการไคลเอ็นต์ต้องยอมรับคําขอ HTTP จากบริการ loadgen จึงต้องติดตั้งใช้งานตัวแฮนเดิล เซิร์ฟเวอร์ HTTP ในบริการไคลเอ็นต์ติดตั้งใช้งานด้วย net/http และคุณใช้แพ็กเกจ otelhttp ได้เช่นเดียวกับที่เราทำใน loadgen

ก่อนอื่น เราจะแทนที่การลงทะเบียนตัวแฮนเดิลด้วยตัวแฮนเดิล otelhttp ในฟังก์ชัน main ให้ค้นหาบรรทัดที่มีการลงทะเบียนตัวแฮนเดิล HTTP ด้วย http.HandleFunc()

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)

จากนั้นเราจะติดตั้งเครื่องมือวัดสแปนจริงภายในตัวแฮนเดิล ค้นหา func (*clientService) handler() และเพิ่มเครื่องมือวัดผลสแปนด้วย trace.SpanFromContext()

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

เครื่องมือวัดนี้จะช่วยให้คุณเห็นช่วงตั้งแต่ต้นของเมธอด handler ไปจนถึงตอนท้าย หากต้องการให้วิเคราะห์ช่วงได้ง่าย ให้เพิ่มแอตทริบิวต์เพิ่มเติมที่จัดเก็บจํานวนรายการที่ตรงกันในคําค้นหา เพิ่มโค้ดต่อไปนี้ก่อนบรรทัดบันทึก

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

การติดตั้งเครื่องมือวัดทั้งหมดข้างต้นเป็นการวัดร่องรอยระหว่าง loadgen กับไคลเอ็นต์เรียบร้อยแล้ว มาดูวิธีการทำงานของฟีเจอร์นี้กัน เรียกใช้โค้ดด้วย skaffold อีกครั้ง

skaffold dev

หลังจากเรียกใช้บริการในคลัสเตอร์ GKE ไปสักพัก คุณจะเห็นข้อความบันทึกจำนวนมากเช่นนี้

เอาต์พุตจากคำสั่ง

[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 จะส่งข้อความเหล่านี้ คุณจะเห็นว่าสแปนหลักของสแปนทั้งหมดจาก loadgen มี TraceID: 00000000000000000000000000000000 เนื่องจากนี่คือสแปนรูท หรือก็คือสแปนแรกในการติดตาม นอกจากนี้ คุณยังพบว่าแอตทริบิวต์การฝัง "query" มีสตริงการค้นหาที่ส่งไปยังบริการลูกค้า

สรุป

ในขั้นตอนนี้ คุณได้เครื่องมือวัดบริการสร้างโหลดและบริการไคลเอ็นต์ที่สื่อสารใน HTTP และยืนยันว่าคุณเผยแพร่บริบทการติดตามในบริการต่างๆ และส่งออกข้อมูล Span จากทั้ง 2 บริการไปยัง stdout ได้สําเร็จ

วิดีโอถัดไป

ในขั้นตอนถัดไป คุณจะใช้เครื่องมือวัดบริการไคลเอ็นต์และบริการเซิร์ฟเวอร์เพื่อยืนยันวิธีเผยแพร่บริบทการติดตามผ่าน gRPC

5. เครื่องมือวัดสำหรับ gRPC

ในขั้นตอนก่อนหน้า เราได้ติดตั้งเครื่องมือสําหรับครึ่งแรกของคําขอในไมโครเซอร์วิสนี้ ในขั้นตอนนี้ เราจะพยายามวัดผลการสื่อสาร gRPC ระหว่างบริการไคลเอ็นต์และบริการเซิร์ฟเวอร์ (สี่เหลี่ยมผืนผ้าสีเขียวและสีม่วงในรูปภาพด้านล่าง)

75310d8e0e3b1a30.png

เครื่องมือวัดผลก่อนการบิลด์สําหรับไคลเอ็นต์ gRPC

ระบบนิเวศของ OpenTelemetry มีไลบรารีที่มีประโยชน์มากมายซึ่งช่วยให้นักพัฒนาแอปพลิเคชันสามารถวัดประสิทธิภาพแอปพลิเคชันได้ ในขั้นตอนก่อนหน้า เราใช้เครื่องมือวัดผลก่อนการบิลด์สําหรับแพ็กเกจ net/http ในขั้นตอนนี้ เราจะใช้ไลบรารีนี้เนื่องจากพยายามที่จะเผยแพร่บริบทการติดตามผ่าน gRPC

ก่อนอื่น ให้นําเข้าแพ็กเกจ gRPC ที่คอมไพล์ไว้ล่วงหน้าชื่อ otelgrpc

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

ในครั้งนี้ บริการไคลเอ็นต์คือไคลเอ็นต์ gRPC กับบริการเซิร์ฟเวอร์ คุณจึงต้องติดตั้งเครื่องมือวัดประสิทธิภาพไคลเอ็นต์ gRPC ค้นหาฟังก์ชัน mustConnGRPC และเพิ่มตัวขัดจังหวะ gRPC ที่เครื่องมือวัดใหม่ทุกครั้งที่ไคลเอ็นต์ส่งคําขอไปยังเซิร์ฟเวอร์

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

คุณไม่จำเป็นต้องตั้งค่าเนื่องจากได้ตั้งค่า OpenTelemetry ไว้แล้วในส่วนก่อนหน้า

เครื่องมือวัดผลที่สร้างไว้ล่วงหน้าสำหรับเซิร์ฟเวอร์ gRPC

เราเรียกเครื่องมือวัดผลที่สร้างไว้ล่วงหน้าสำหรับเซิร์ฟเวอร์ gRPC เช่นเดียวกับที่ทำกับไคลเอ็นต์ gRPC เพิ่มแพ็กเกจใหม่ลงในส่วนการนําเข้า เช่น

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

เนื่องจากนี่เป็นการใช้งานเซิร์ฟเวอร์เป็นครั้งแรก คุณจึงต้องตั้งค่า OpenTelemetry ก่อน เช่นเดียวกับที่เราทํากับบริการ loadgen และไคลเอ็นต์

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

ถัดไป คุณต้องเพิ่มตัวสกัดกั้นเซิร์ฟเวอร์ ในฟังก์ชัน main ให้ค้นหาตำแหน่งที่มีการเรียก grpc.NewServer() และเพิ่มตัวขัดจังหวะลงในฟังก์ชัน

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

เรียกใช้ไมโครเซอร์วิสและยืนยันการติดตาม

จากนั้นเรียกใช้โค้ดที่แก้ไขแล้วด้วยคําสั่ง skaffold

skaffold dev

ตอนนี้คุณจะเห็นข้อมูลสแปนจำนวนมากใน stdout

เอาต์พุตจากคำสั่ง

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

คุณสังเกตเห็นว่าไม่ได้ฝังชื่อช่วงและไม่ได้สร้างช่วงด้วย trace.Start() หรือ span.SpanFromContext() ด้วยตนเอง แต่คุณยังคงเห็นสแปนจำนวนมากเนื่องจากตัวขัดจังหวะ gRPC สร้างขึ้น

สรุป

ในขั้นตอนนี้ คุณจะวัดผลการสื่อสารแบบ gRPC โดยได้รับความช่วยเหลือจากไลบรารีระบบนิเวศ OpenTelemetry

วิดีโอถัดไป

ในขั้นตอนถัดไป คุณจะเห็นภาพการติดตามด้วย Cloud Trace และเรียนรู้วิธีวิเคราะห์ช่วงข้อมูลที่รวบรวม

6. แสดงภาพการติดตามด้วย Cloud Trace

คุณได้ติดตั้งเครื่องมือวัดร่องรอยในทั้งระบบด้วย OpenTelemetry คุณได้เรียนรู้วิธีตรวจสอบบริการ HTTP และ gRPC ไปแล้ว แม้ว่าคุณจะได้เรียนรู้วิธีวัดผลแล้ว แต่ก็ยังไม่ทราบวิธีวิเคราะห์ ในส่วนนี้ คุณจะนำตัวส่งออก stdout ไปแทนที่ตัวส่งออก Cloud Trace และเรียนรู้วิธีวิเคราะห์การติดตาม

ใช้เครื่องมือส่งออก Cloud Trace

ลักษณะที่มีประสิทธิภาพอย่างหนึ่งของ OpenTelemetry คือความสามารถในการเสียบ หากต้องการแสดงภาพสแปนที่เครื่องมือวัดรวบรวมทั้งหมด สิ่งที่คุณต้องทำคือแทนที่ตัวส่งออก stdout ด้วยตัวส่งออก Cloud Trace

เปิดไฟล์ main.go ของบริการแต่ละรายการ แล้วค้นหาฟังก์ชัน initTracer() ลบบรรทัดเพื่อสร้างตัวส่งออก stdout และสร้างตัวส่งออก Cloud Trace แทน

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
}

คุณต้องแก้ไขฟังก์ชันเดียวกันในบริการไคลเอ็นต์และเซิร์ฟเวอร์ด้วย

เรียกใช้ไมโครเซอร์วิสและยืนยันการติดตาม

หลังจากแก้ไขแล้ว ให้เรียกใช้คลัสเตอร์ตามปกติด้วยคำสั่ง skaffold

skaffold dev

ตอนนี้คุณจึงไม่เห็นข้อมูลช่วงมากนักในรูปแบบบันทึกที่มีโครงสร้างใน stdout เนื่องจากคุณแทนที่เครื่องมือส่งออกด้วยเครื่องมือ Cloud Trace แล้ว

เอาต์พุตจากคำสั่ง

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

ตอนนี้มาตรวจสอบกันว่าระบบส่งสแปนทั้งหมดไปยัง Cloud Trace อย่างถูกต้องหรือไม่ เข้าถึง Cloud Console แล้วไปที่ "รายการการติดตาม" เข้าถึงได้ง่ายจากช่องค้นหา หรือคลิกเมนูในแผงด้านซ้ายก็ได้ 8b3f8411bd737e06.png

จากนั้นคุณจะเห็นจุดสีน้ำเงินจำนวนมากกระจายอยู่ในกราฟเวลาในการตอบสนอง โดยแต่ละจุดแสดงการติดตาม 1 รายการ

3ecf131423fc4c40.png

คลิกรายการใดรายการหนึ่งแล้วคุณจะเห็นรายละเอียดในการติดตาม 4fd10960c6648a03.png

คุณจะเห็นข้อมูลเชิงลึกมากมายได้จากการดูข้อมูลคร่าวๆ นี้ ตัวอย่างเช่น จากกราฟ Waterfall คุณจะเห็นสาเหตุของเวลาในการตอบสนองส่วนใหญ่มาจากช่วงที่มีชื่อว่า shakesapp.ShakespeareService/GetMatchCount (ดู 1 ในรูปภาพด้านบน) คุณสามารถยืนยันได้จากตารางสรุป (คอลัมน์ด้านขวาสุดแสดงระยะเวลาของช่วงแต่ละช่วง) นอกจากนี้ การติดตามนี้ยังใช้กับการค้นหา "เพื่อน" ด้วย (ดู 2 ในรูปภาพด้านบน)

จากการวิเคราะห์สั้นๆ เหล่านี้ คุณอาจพบว่าคุณต้องทราบช่วงเวลาที่ละเอียดยิ่งขึ้นภายในเมธอด GetMatchCount การแสดงภาพมีประสิทธิภาพมากกว่าข้อมูล stdout ดูข้อมูลเพิ่มเติมเกี่ยวกับรายละเอียดการติดตามในระบบคลาวด์ได้ที่เอกสารประกอบอย่างเป็นทางการ

สรุป

ในขั้นตอนนี้ คุณได้แทนที่เครื่องมือส่งออก stdout ด้วยเครื่องมือส่งออก Cloud Trace และแสดงภาพร่องรอยใน Cloud Trace นอกจากนี้ คุณยังได้เรียนรู้วิธีเริ่มวิเคราะห์ร่องรอย

วิดีโอถัดไป

ในขั้นตอนถัดไป คุณจะแก้ไขซอร์สโค้ดของบริการเซิร์ฟเวอร์เพื่อเพิ่มช่วงย่อยใน GetMatchCount

7. เพิ่มช่วงย่อยเพื่อให้การวิเคราะห์ดีขึ้น

ในขั้นตอนก่อนหน้า คุณได้พบว่าสาเหตุของเวลาในการไปกลับที่สังเกตได้จาก loadgen ส่วนใหญ่เป็นกระบวนการภายในเมธอด GetMatchCount ซึ่งเป็นตัวแฮนเดิล gRPC ในบริการเซิร์ฟเวอร์ อย่างไรก็ตาม เนื่องจากเราไม่ได้ติดตั้งเครื่องมือวัดผลอื่นๆ นอกเหนือจากตัวแฮนเดิล เราจึงไม่สามารถค้นหาข้อมูลเชิงลึกเพิ่มเติมจากกราฟ Waterfall กรณีนี้เกิดขึ้นได้บ่อยเมื่อเราเริ่มเครื่องมือวัดประสิทธิภาพไมโครเซอร์วิส

3b63a1e471dddb8c.png

ในส่วนนี้ เราจะติดตั้งเครื่องมือวัดค่าสแปนย่อยเมื่อเซิร์ฟเวอร์เรียกใช้ Google Cloud Storage เนื่องจากเป็นเรื่องปกติที่ I/O เครือข่ายภายนอกบางรายการจะใช้เวลานานในกระบวนการ และเราต้องระบุว่าการเรียกใช้คือสาเหตุหรือไม่

ติดตั้งเครื่องมือวัดใน Span ย่อยในเซิร์ฟเวอร์

เปิด main.go ในเซิร์ฟเวอร์ แล้วค้นหาฟังก์ชัน readFiles ฟังก์ชันนี้จะเรียกคําขอไปยัง Google Cloud Storage เพื่อดึงข้อมูลไฟล์ข้อความทั้งหมดของผลงานของ Shakespeare ในฟังก์ชันนี้ คุณสามารถสร้างช่วงย่อยได้ เช่นเดียวกับที่ทำในเครื่องมือวัดเซิร์ฟเวอร์ HTTP ในบริการไคลเอ็นต์

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

เท่านี้ก็เพิ่มช่วงใหม่ได้แล้ว มาดูผลลัพธ์กันด้วยการเรียกใช้แอป

เรียกใช้ไมโครเซอร์วิสและยืนยันการติดตาม

หลังจากแก้ไขแล้ว ให้เรียกใช้คลัสเตอร์ตามปกติด้วยคำสั่ง skaffold

skaffold dev

แล้วเลือกการติดตามชื่อ query.request รายการใดรายการหนึ่งจากรายการการติดตาม คุณจะเห็นกราฟ Waterfall ของการติดตามที่คล้ายกัน ยกเว้นช่วงใหม่ในส่วน shakesapp.ShakespeareService/GetMatchCount (ช่วงที่ถูกล้อมรอบด้วยสี่เหลี่ยมผืนผ้าสีแดงด้านล่าง)

3d4a891aa30d7a32.png

สิ่งที่คุณบอกได้จากกราฟนี้คือการเรียกใช้ภายนอกไปยัง Google Cloud Storage ใช้เวลาในการตอบสนองนานมาก แต่ยังมีสิ่งอื่นๆ ที่ทำให้เกิดความล่าช้าส่วนใหญ่

คุณได้รับข้อมูลเชิงลึกมากมายแล้วจากการดูกราฟ Waterfall ของการติดตามเพียง 2-3 ครั้ง คุณดูรายละเอียดประสิทธิภาพเพิ่มเติมในแอปพลิเคชันได้อย่างไร เครื่องมือวิเคราะห์จะเข้ามามีบทบาทในขั้นตอนนี้ แต่ตอนนี้เราขอจบ Codelab นี้และส่งต่อบทแนะนำเครื่องมือวิเคราะห์ทั้งหมดไปยังส่วนที่ 2

สรุป

ในขั้นตอนนี้ คุณได้ติดตั้งใช้งานช่วงในบริการเซิร์ฟเวอร์อีกช่วงหนึ่งและรับข้อมูลเชิงลึกเพิ่มเติมเกี่ยวกับเวลาในการตอบสนองของระบบ

8. ขอแสดงความยินดี

คุณสร้างการติดตามแบบกระจายด้วย OpenTelemery และยืนยันเวลาในการตอบสนองของคําขอในไมโครเซอร์วิสใน Google Cloud Trace เรียบร้อยแล้ว

หากต้องการทำแบบฝึกหัดเพิ่มเติม คุณสามารถลองทำหัวข้อต่อไปนี้ด้วยตนเอง

  • การใช้งานปัจจุบันจะส่งสแปนทั้งหมดที่การตรวจสอบประสิทธิภาพสร้างขึ้น (grpc.health.v1.Health/Check) คุณกรองช่วงเหล่านั้นออกจาก Cloud Trace ได้อย่างไร ดูคำแนะนำได้ที่นี่
  • เชื่อมโยงบันทึกเหตุการณ์กับช่วง และดูวิธีการทํางานใน Google Cloud Trace และ Google Cloud Logging ดูคำแนะนำได้ที่นี่
  • แทนที่บริการบางอย่างด้วยบริการในภาษาอื่น แล้วลองใช้เครื่องมือวัดผลด้วย OpenTelemetry สำหรับภาษานั้น

นอกจากนี้ หากต้องการดูข้อมูลเกี่ยวกับเครื่องมือวิเคราะห์โปรไฟล์หลังจากนี้ โปรดไปที่ส่วนที่ 2 ในกรณีนี้ คุณสามารถข้ามส่วน "ล้างข้อมูล" ด้านล่างได้

ล้างข้อมูล

หลังจากทำ Codelab นี้เสร็จแล้ว โปรดหยุดคลัสเตอร์ Kubernetes และอย่าลืมลบโปรเจ็กต์เพื่อไม่ให้เกิดการเรียกเก็บเงินที่ไม่คาดคิดใน Google Kubernetes Engine, Google Cloud Trace, Google Artifact Registry

ก่อนอื่น ให้ลบคลัสเตอร์ หากเรียกใช้คลัสเตอร์ด้วย skaffold dev คุณก็แค่กด Ctrl-C หากคุณเรียกใช้คลัสเตอร์ด้วย skaffold run ให้เรียกใช้คําสั่งต่อไปนี้

skaffold delete

เอาต์พุตจากคำสั่ง

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

หลังจากลบคลัสเตอร์แล้ว ให้เลือก "IAM และผู้ใช้ที่ดูแลระบบ" > "การตั้งค่า" จากแผงเมนู แล้วคลิกปุ่ม "ปิดระบบ"

45aa37b7d5e1ddd1.png

จากนั้นป้อนรหัสโปรเจ็กต์ (ไม่ใช่ชื่อโปรเจ็กต์) ในแบบฟอร์มในกล่องโต้ตอบและยืนยันการปิด