1. 簡介
上次更新時間:2022 年 7 月 14 日
應用程式的觀測能力
觀測能力和持續分析器
「觀測能力」是指用來描述系統屬性的字詞。具備觀測能力的系統可讓團隊主動偵錯。在這些情境下,觀測能力的三大要素;記錄、指標和追蹤記錄是系統取得觀測能力的基本檢測標準。
除了觀測能力的三大要素以外,持續分析是觀測能力的另一個關鍵要素,同時在業界擴大使用者族群。Cloud Profiler 是來源系統之一,您可透過簡單易用的介面細查應用程式呼叫堆疊中的效能指標。
本程式碼研究室是本系列文章的第 2 部分,說明如何檢測連續分析器代理程式。第 1 部分涵蓋利用 OpenTelemetry 和 Cloud Trace 的分散式追蹤功能,第 1 部分會說明如何更妥善地找出微服務的瓶頸。
建構項目
在本程式碼研究室中,您要在「Shakespeare application」的伺服器服務中檢測連續分析器代理程式。(又稱「Shakesapp」) 使用 Google Kubernetes Engine 叢集Shakesapp 的架構如下:
- Loadgen 使用 HTTP 將查詢字串傳送至用戶端
- 用戶端將查詢從 loadgen 傳遞至 gRPC 中的伺服器
- 伺服器接受從用戶端查詢、從 Google Cloud Storage 擷取所有 Shakespare 都能以文字格式運作、搜尋包含查詢的行,並傳回與用戶端相符的該行數
在第 1 部分,您發現瓶頸存在伺服器服務的某處,但無法識別確切原因。
課程內容
- 如何嵌入分析器代理程式
- 如何調查 Cloud Profiler 中的瓶頸
本程式碼研究室說明如何在應用程式中檢測連續分析器代理程式。
軟硬體需求
- Go 基本知識
- Kubernetes 的基本知識
2. 設定和需求
自修環境設定
如果您還沒有 Google 帳戶 (Gmail 或 Google Apps),請先建立帳戶。登入 Google Cloud Platform 控制台 ( console.cloud.google.com),並建立新專案。
如果您已有專案,請按一下控制台左上方的專案選取下拉式選單:
並點選 [新增專案]按鈕,用於建立新專案:
如果您還沒有專案,系統會顯示如下的對話方塊,讓您建立第一個專案:
後續的專案建立對話方塊可讓您輸入新專案的詳細資料:
請記住,專案 ID 在所有的 Google Cloud 專案中是不重複的名稱 (已經有人使用上述名稱,目前無法為您解決問題!)。稍後在本程式碼研究室中會稱為 PROJECT_ID。
接下來,如果您尚未在 Developers Console 中啟用計費功能,您需要先在 Developers Console 中啟用計費功能,才能使用 Google Cloud 資源並啟用 Cloud Trace API。
執行本程式碼研究室所需的費用不應超過數美元,但如果您決定使用更多資源,或讓這些資源繼續運作,費用會增加 (請參閱本文件結尾的「清理」一節)。如需 Google Cloud Trace、Google Kubernetes Engine 和 Google Artifact Registry 的定價資訊,請參閱官方說明文件。
Google Cloud Platform 的新使用者符合 $300 美元的免費試用資格,應該可以免費使用本程式碼研究室。
Google Cloud Shell 設定
雖然 Google Cloud 和 Google Cloud Trace 可以在筆記型電腦上遠端運作,但在本程式碼研究室中,我們會使用 Google Cloud Shell,這是一種在 Cloud 中執行的指令列環境。
這種以 Debian 為基礎的虛擬機器,搭載各種您需要的開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。換言之,本程式碼研究室只需要在 Chromebook 上運作即可。
如要透過 Cloud 控制台啟用 Cloud Shell,只要點選「啟用 Cloud Shell」圖示 ,即可佈建並連線至環境,操作只需幾分鐘的時間。
連線至 Cloud Shell 後,您應會發現自己通過驗證,且專案已設為 PROJECT_ID
。
gcloud auth list
指令輸出
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
指令輸出
[core] project = <PROJECT_ID>
如因故未設定專案,請直接發出以下指令:
gcloud config set project <PROJECT_ID>
正在尋找 PROJECT_ID
嗎?查看您在設定步驟中使用的 ID,或在 Cloud 控制台資訊主頁查詢:
根據預設,Cloud Shell 也會設定一些環境變數,方便您之後執行指令。
echo $GOOGLE_CLOUD_PROJECT
指令輸出
<PROJECT_ID>
最後,進行預設可用區和專案設定。
gcloud config set compute/zone us-central1-f
您可以選擇各種不同的可用區。詳情請參閱「區域與可用區。
Go 語言設定
在本程式碼研究室中,我們會針對所有原始碼使用 Go。在 Cloud Shell 執行下列指令,並確認 Go 的版本是否為 1.17 以上版本
go version
指令輸出
go version go1.18.3 linux/amd64
設定 Google Kubernetes 叢集
在本程式碼研究室中,您將在 Google Kubernetes Engine (GKE) 執行微服務叢集。本程式碼研究室的流程如下:
- 將基準專案下載至 Cloud Shell
- 將微服務建構至容器
- 將容器上傳至 Google Artifact Registry (GAR)
- 將容器部署至 GKE
- 修改追蹤記錄檢測服務的原始碼
- 前往步驟 2
啟用 Kubernetes Engine
首先,我們設定了一個 Kubernetes 叢集,讓 Shakesapp 在 GKE 上執行,因此必須啟用 GKE。前往「Kubernetes Engine」選單然後按下「啟用」按鈕
您現在可以建立 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」的選單然後按下「啟用」按鈕
一段時間後,您會看到 GAR 的存放區瀏覽器。按一下 [建立存放區]按鈕,然後輸入存放區名稱。
在本程式碼研究室中,我會將新存放區命名為 trace-codelab
。構件的格式為「Docker」地點類型為「區域」選擇接近您為 Google Compute Engine 預設可用區設定的區域。以下範例選擇「us-central1-f」上方,我們選擇「us-central1 (愛荷華州)」接著按一下「建立」按鈕。
現在您會看到複製到存放區瀏覽器
稍後會再回來檢查登錄路徑。
Skaffold 設定
如要建構在 Kubernetes 上執行的微服務,Skaffold 是相當實用的工具。這個工具包只需使用少量指令,就能處理建構、推送及部署應用程式容器的工作流程。根據預設,Skaffold 會使用 Docker Registry 做為容器登錄檔,因此您需要設定 skaffold 來辨識 GAR,以將容器推送到容器。
再次開啟 Cloud Shell,並確認是否已安裝 skaffold。(Cloud Shell 預設會在環境中安裝 Skaffold。)執行下列指令並查看 Skaffold 版本。
skaffold version
指令輸出
v1.38.0
現在,您可以註冊使用 Skaffold 的預設存放區。如要取得登錄檔路徑,請前往 Artifact Registry 資訊主頁,然後按一下您在上一個步驟中設定的存放區名稱。
您就會在頁面頂端看到導覽標記記錄。按一下 圖示,將登錄路徑複製到剪貼簿。
按一下「複製」按鈕後,您會在瀏覽器底部看到含有下列訊息的對話方塊:
"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
您現在可以前往下一個步驟,在 GKE 中設定 Kubernetes 容器。
摘要
在這個步驟中,您會設定程式碼研究室環境:
- 設定 Cloud Shell
- 已為 Container Registry 建立 Artifact Registry 存放區
- 設定 skaffold 以使用 Container Registry
- 建立用於執行程式碼研究室微服務的 Kubernetes 叢集
下一步
在下一個步驟中,您要在伺服器服務中檢測連續分析器代理程式。
3. 建構、推送及部署微服務
下載程式碼研究室教材
在上一個步驟中,我們已設定本程式碼研究室的所有必備條件。您現在可以透過這些微服務執行整個微服務了。程式碼研究室的內容託管於 GitHub,請使用以下 Git 指令將這些內容下載至 Cloud Shell 環境。
cd ~ git clone https://github.com/ymotongpoo/opentelemetry-trace-codelab-go.git cd opentelemetry-trace-codelab-go
專案的目錄結構如下:
. ├── README.md ├── step0 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step1 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step2 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step3 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step4 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step5 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src └── step6 ├── manifests ├── proto ├── skaffold.yaml └── src
- 資訊清單:Kubernetes 資訊清單檔案
- proto:用戶端和伺服器通訊的 Proto 定義
- src: 每個服務的原始碼目錄
- skaffold.yaml:skaffold 的設定檔
在本程式碼研究室中,您將更新 step4
資料夾下的原始碼。如果想從頭開始,也可以參考 step[1-6]
資料夾中的原始碼。(第 1 部分涵蓋步驟 0 到步驟 4,第 2 部分涵蓋步驟 5 和 6)
執行 skaffold 指令
最後,您可以開始建構完整內容,並將完整內容推送至剛剛建立的 Kubernetes 叢集。這聽起來似乎包含多個步驟,但其實 Skaffold 可以為您執行所有操作。請使用下列指令:
cd step4 skaffold dev
執行指令後,您會看到 docker build
的記錄輸出,並且可以確認已成功推送至登錄檔。
指令輸出
... ---> Running in c39b3ea8692b ---> 90932a583ab6 Successfully built 90932a583ab6 Successfully tagged us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step1 The push refers to repository [us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice] cc8f5a05df4a: Preparing 5bf719419ee2: Preparing 2901929ad341: Preparing 88d9943798ba: Preparing b0fdf826a39a: Preparing 3c9c1e0b1647: Preparing f3427ce9393d: Preparing 14a1ca976738: Preparing f3427ce9393d: Waiting 14a1ca976738: Waiting 3c9c1e0b1647: Waiting b0fdf826a39a: Layer already exists 88d9943798ba: Layer already exists f3427ce9393d: Layer already exists 3c9c1e0b1647: Layer already exists 14a1ca976738: Layer already exists 2901929ad341: Pushed 5bf719419ee2: Pushed cc8f5a05df4a: Pushed step1: digest: sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe size: 2001
所有服務容器推送完畢後,Kubernetes Deployment 就會自動啟動。
指令輸出
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
摘要
在這個步驟中,您已準備好環境中的程式碼研究室教材,並確認 Skaffold 可以正常執行。
下一步
在下一個步驟中,您將修改 loadgen 服務的原始碼,以檢測追蹤記錄資訊。
4. 檢測 Cloud Profiler 代理程式
持續剖析概念
在說明持續剖析的概念之前,我們需要先瞭解剖析的概念。剖析是動態分析應用程式 (動態程式分析) 的方法之一,通常會在應用程式的開發期間,於負載測試等期間執行。在特定期間,用於測量系統指標 (例如 CPU 和記憶體用量) 的單樣本活動。收集設定檔資料後,開發人員分析這些資訊,
持續剖析是一般剖析的延伸方法:它會定期針對長時間執行的應用程式執行短視窗剖析,並收集大量設定檔資料。接著,這個 API 會根據應用程式的特定屬性 (例如版本號碼、部署時區、測量時間等),自動產生統計分析。如要進一步瞭解這個概念,請參閱說明文件。
由於目標是執行中的應用程式,因此可定期收集設定檔資料,並傳送至某些後端處理統計資料的後端。這是 Cloud Profiler 代理程式,您很快就會將它嵌入伺服器服務。
嵌入 Cloud Profiler 代理程式
按下 Cloud Shell 右上角的 按鈕,開啟 Cloud Shell 編輯器。在左側窗格中的探索工具中開啟
step4/src/server/main.go
,然後找出主要函式。
step4/src/server/main.go
func main() { ... // step2. setup OpenTelemetry tp, err := initTracer() if err != nil { log.Fatalf("failed to initialize TracerProvider: %v", err) } defer func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatalf("error shutting down TracerProvider: %v", err) } }() // step2. end setup svc := NewServerService() // step2: add interceptor interceptorOpt := otelgrpc.WithTracerProvider(otel.GetTracerProvider()) srv := grpc.NewServer( grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor(interceptorOpt)), grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor(interceptorOpt)), ) // step2: end adding interceptor shakesapp.RegisterShakespeareServiceServer(srv, svc) healthpb.RegisterHealthServer(srv, svc) if err := srv.Serve(lis); err != nil { log.Fatalf("error serving server: %v", err) } }
在 main
函式中,您會看到一些 OpenTelemetry 和 gRPC 的設定程式碼,已在程式碼研究室的第 1 部分完成。現在您要在這裡新增 Cloud Profiler 代理程式的檢測設備。和我們為 initTracer()
所做的一樣,您可以編寫名為 initProfiler()
的函式以便閱讀。
step4/src/server/main.go
import ( ... "cloud.google.com/go/profiler" // step5. add profiler package "cloud.google.com/go/storage" ... ) // step5: add Profiler initializer func initProfiler() { cfg := profiler.Config{ Service: "server", ServiceVersion: "1.0.0", NoHeapProfiling: true, NoAllocProfiling: true, NoGoroutineProfiling: true, NoCPUProfiling: false, } if err := profiler.Start(cfg); err != nil { log.Fatalf("failed to launch profiler agent: %v", err) } }
讓我們仔細看看 profiler.Config{}
物件中指定的選項。
- 服務:可以在分析器資訊主頁中選取及切換的服務名稱
- ServiceVersion:服務版本名稱。您可以根據這個值比較設定檔資料集。
- NoHeapProfiling:停用記憶體用量分析功能
- NoAllocProfiling:停用記憶體配置剖析
- NoGoroutineProfiling:停用 Goroutine 剖析
- NoCPUProfiling:停用 CPU 剖析
在本程式碼研究室中,我們只會啟用 CPU 剖析功能。
現在,只需在 main
函式中呼叫這個函式即可。請務必在匯入區塊中匯入 Cloud Profiler 套件。
step4/src/server/main.go
func main() { ... defer func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatalf("error shutting down TracerProvider: %v", err) } }() // step2. end setup // step5. start profiler go initProfiler() // step5. end svc := NewServerService() // step2: add interceptor ... }
請注意,您將使用 go
關鍵字呼叫 initProfiler()
函式。因為 profiler.Start()
會封鎖,所以您必須在另一個 Go 常式中執行。現在可以開始建構了。請務必在部署前執行 go mod tidy
。
go mod tidy
現在使用新的伺服器服務來部署叢集。
skaffold dev
通常會在幾分鐘內看到 Cloud Profiler 的火焰圖。輸入「profiler」,然後按一下 Profiler 圖示。
然後,您會看見以下火焰圖。
摘要
在這個步驟中,您已成功將 Cloud Profiler 代理程式嵌入伺服器服務,並確認該代理程式會產生火焰圖。
下一步
在下一個步驟中,您將使用火焰圖調查應用程式瓶頸的原因。
5. 分析 Cloud Profiler 火焰圖
什麼是 Flame Graph?
火焰圖是視覺化呈現設定檔資料的方法之一。如需詳細的解釋,請參閱我們的文件,但摘要內容如下:
- 每個長條都代表應用程式中的方法/函式呼叫
- 垂直方向為呼叫堆疊;從上到下增長
- 水平方向是指資源用量;時間越長越好
有鑑於此,我們來看看取得的火焰圖。
分析火焰圖
在上一節中,您瞭解火焰圖中的每個長條都代表函式/方法呼叫,而其長度代表函式/方法中的資源用量。Cloud Profiler 的火焰圖會以遞減順序或由左至右為長度排序長條,因此請先檢視圖表的左上角。
在我們的例子中,明確表示 grpc.(*Server).serveStreams.func1.2
耗用了大部分的 CPU 作業時間,且藉由從頂端到底部檢視呼叫堆疊,所花費的時間大多是在 main.(*serverService).GetMatchCount
中,也就是伺服器服務中的 gRPC 伺服器處理常式。
在 GetMatchCount 下方,您會看到一系列規則運算式函式:regexp.MatchString
和 regexp.Compile
。這些範例皆來自標準套件,也就是應該從許多觀點妥善測試,包括效能。但這裡的結果顯示 regexp.MatchString
和 regexp.Compile
中的 CPU 作業時間資源用量偏高。根據這些事實,這裡的假設是,使用 regexp.MatchString
與效能問題有關。接著我們來讀取使用該函式的原始碼。
step4/src/server/main.go
func (s *serverService) GetMatchCount(ctx context.Context, req *shakesapp.ShakespeareRequest) (*shakesapp.ShakespeareResponse, error) { resp := &shakesapp.ShakespeareResponse{} texts, err := readFiles(ctx, bucketName, bucketPrefix) if err != nil { return resp, fmt.Errorf("fails to read files: %s", err) } for _, text := range texts { for _, line := range strings.Split(text, "\n") { line, query := strings.ToLower(line), strings.ToLower(req.Query) isMatch, err := regexp.MatchString(query, line) if err != nil { return resp, err } if isMatch { resp.MatchCount++ } } } return resp, nil }
這就是呼叫 regexp.MatchString
的位置。讀取原始碼後,您可能會發現函式會在巢狀 For-loop 中呼叫。因此這個函式的使用方式可能有誤。我們來查詢 regexp 的 GoDoc。
根據文件,regexp.MatchString
會在每次呼叫時編譯規則運算式模式。造成大量資源消耗的原因聽起來像這個樣子。
摘要
在這個步驟中,您藉由分析火焰圖來假設使用資源消耗的原因。
下一步
在下一個步驟中,您將更新伺服器服務的原始碼,並確認是否為 1.0.0 版所做的變更。
6. 更新原始碼並比較火焰圖
更新原始碼
在上一個步驟中,您假設使用 regexp.MatchString
與大量資源耗用有關。讓我們解決這個問題吧開啟程式碼並稍微修改該部分。
step4/src/server/main.go
func (s *serverService) GetMatchCount(ctx context.Context, req *shakesapp.ShakespeareRequest) (*shakesapp.ShakespeareResponse, error) { resp := &shakesapp.ShakespeareResponse{} texts, err := readFiles(ctx, bucketName, bucketPrefix) if err != nil { return resp, fmt.Errorf("fails to read files: %s", err) } // step6. considered the process carefully and naively tuned up by extracting // regexp pattern compile process out of for loop. query := strings.ToLower(req.Query) re := regexp.MustCompile(query) for _, text := range texts { for _, line := range strings.Split(text, "\n") { line = strings.ToLower(line) isMatch := re.MatchString(line) // step6. done replacing regexp with strings if isMatch { resp.MatchCount++ } } } return resp, nil }
如您所見,現在系統會從 regexp.MatchString
中擷取規則運算式模式編譯程序,並移出巢狀 for 迴圈。
部署此程式碼之前,請務必更新 initProfiler()
函式中的版本字串。
step4/src/server/main.go
func initProfiler() { cfg := profiler.Config{ Service: "server", ServiceVersion: "1.1.0", // step6. update version NoHeapProfiling: true, NoAllocProfiling: true, NoGoroutineProfiling: true, NoCPUProfiling: false, } if err := profiler.Start(cfg); err != nil { log.Fatalf("failed to launch profiler agent: %v", err) } }
接著來看看運作方式使用 skaffold 指令部署叢集。
skaffold dev
過一段時間後,請重新載入 Cloud Profiler 資訊主頁,看看情況如何。
請務必將版本變更為 "1.1.0"
,只查看 1.1.0 版的設定檔。如您所知,GetMatchCount 的長條長度降低以及 CPU 作業時間的使用率 (即長條變少)。
您不僅可以查看單一版本的火焰圖,還能比較兩個版本的差異。
變更「比較」的值變更為「版本」然後變更「比較版本」的值「1.0.0」代表原始版本。
您會看到這種火焰圖。圖表的形狀與 1.1.0 相同,但顏色不同。在「比較模式」中,色彩代表的意義:
- 藍色:減少的值 (資源用量)
- 橘色:增加的值 (資源用量)
- 灰色:中性
透過圖例,讓我們進一步瞭解函式。只要點選要放大的長條,即可在堆疊中查看更多詳細資訊。請按一下 main.(*serverService).GetMatchCount
長條。此外,將滑鼠遊標懸停在長條上,即可查看比較的詳細資料。
表示 CPU 總作業時間從 5.26 減少至 2.88 秒 (總數為 10 秒 = 取樣期)。進步幅度相當大!
您現在可以透過分析設定檔資料來改善應用程式效能。
摘要
在這個步驟中,您編輯了伺服器服務,並確認 Cloud Profiler 比較模式的改善幅度。
下一步
在下一個步驟中,您將更新伺服器服務的原始碼,並確認是否為 1.0.0 版所做的變更。
7. 額外步驟:確認 Trace 刊登序列中的改善程度
分散式追蹤記錄和持續剖析的差異
在程式碼研究室的第 1 部分,您已確認自己可以找出要求路徑的微服務中瓶頸服務,而且無法找出特定服務中瓶頸的確切原因。在第 2 單元程式碼研究室中,您已瞭解持續剖析功能可讓您從呼叫堆疊中找出單一服務中的瓶頸。
在這個步驟中,我們要透過分散式追蹤記錄 (Cloud Trace) 查看瀑布圖,瞭解持續剖析的成效差異。
此瀑布圖是包含查詢「love」的追蹤記錄之一。總共需要約 6.7 秒 (6700 毫秒)。
這已改善同一個查詢的服務品質。如您所知,總延遲時間現在為 1.5 秒 (1500 毫秒),與先前的實作相比,是極大的進步。
重點在於,在分散式追蹤記錄刊登序列圖表中,您必須檢測周圍的跨範圍,才能取得呼叫堆疊資訊。另外,分散式追蹤記錄只會著重在服務之間的延遲,而持續剖析則著重於單一服務的電腦資源 (CPU、記憶體、OS 執行緒)。
另一方面,分散式追蹤記錄是事件基礎,連續設定檔屬於統計資料。每個追蹤記錄的延遲時間圖表都不同,因此您需要採用分佈等其他格式,才能掌握延遲變化的趨勢。
摘要
在這個步驟中,您檢查了分散式追蹤記錄和持續剖析之間的差異。
8. 恭喜
您已成功透過 OpenTelemery 建立分散式追蹤記錄,並確認 Google Cloud Trace 上微服務的要求延遲時間。
對於延長的運動,您可以自行嘗試下列主題。
- 目前的實作項目會傳送健康狀態檢查產生的所有時距。(
grpc.health.v1.Health/Check
) 您如何從 Cloud Trace 中篩除這些時距?提示請參閱這裡。 - 將事件記錄與時距建立關聯,並觀察記錄在 Google Cloud Trace 和 Google Cloud Logging 中的運作方式。提示請參閱這裡。
- 請將某些服務替換為其他語言,並嘗試以該語言的 OpenTelemetry 檢測服務。
此外,如果想進一步瞭解分析器,請前往第 2 部分。在這種情況下,您可以略過下方的清理作業一節。
清理
在這個程式碼研究室中,請停止 Kubernetes 叢集並確實刪除專案,以免在 Google Kubernetes Engine、Google Cloud Trace 和 Google Artifact Registry 中產生非預期的費用。
首先,請刪除叢集。如果您使用 skaffold dev
執行叢集,只要按下 Ctrl-C 鍵即可。如果您使用 skaffold run
執行叢集,請執行下列指令:
skaffold delete
指令輸出
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
刪除叢集後,請從選單窗格中選取「IAM 與管理員」>,然後按一下「SHUT DOWN」按鈕。
然後在對話方塊中的表單中輸入專案 ID (而非專案名稱),並確認關閉。