應用程式效能管理 (APM) 簡介
在雲端原生微服務的世界中,「能跑」是不夠的。「高效地運行」才是目標。Google Cloud 上的 Application Performance Management (APM) 是一套旨在幫助架構師和開發人員識別、分析和解決應用程式效能瓶頸的工具。GCP 的 APM 核心方案由 Cloud Trace、Cloud Profiler 和 Cloud Debugger(現已整合到更廣泛的運維套件中)組成。
對於 GCP Professional Cloud Architect (PCA) 考試,你必須了解如何使用這些工具來減少延遲、優化資源消耗(進而降低成本)並改善終端使用者體驗。
白話文解釋 Application Performance Management
比喻 1 — 主廚的廚房
想像一個繁忙的餐廳廚房。Cloud Trace 就像一個秒錶,追蹤從服務生接單到食物送上桌的每一個環節。如果牛排遲到了,Trace 會告訴你是烤架、備料站還是裝飾站出了問題。Cloud Profiler 則像是一台隱藏式攝影機,觀察廚師如何移動;它會注意到某位廚師花了 40% 的時間只是在找一把特定的刀,這建議你應該把刀架移近一點(程式碼優化)。
比喻 2 — 包裹遞送服務
APM 就像是快遞公司的 GPS 追蹤系統。如果包裹(Request)延遲了,Cloud Trace 會精確顯示是哪個分揀設施或送貨卡車耽擱了。Cloud Profiler 則分析送貨卡車的引擎,看看它們相對於行駛距離是否燃燒了過多燃料(CPU/記憶體),幫助你選擇更高效的引擎。
比喻 3 — 醫療健康檢查
Cloud Monitoring 告訴你病人發燒了(高 CPU 使用率)。Cloud Trace 是 X 光,顯示在特定活動中具體是哪個器官在掙扎。Cloud Profiler 則是血液檢查,從細胞層級(函式呼叫)觀察為什麼身體即使在休息時也消耗這麼多能量。
一種用於監控應用程式(尤其是構建在微服務架構上的應用程式)的方法,透過追蹤單個請求在移動經過各種服務和組件時的路徑。
GCP APM 的核心組件
1. Cloud Trace (分散式追蹤)
Cloud Trace 從你的應用程式收集延遲數據,並將其顯示在 Google Cloud 控制台中。
- Span: Trace 中的單個操作(例如:RPC 呼叫、資料庫查詢)。
- Trace: Span 的集合,代表一個請求的端到端旅程。
- 分析報告 (Analysis Reports): 透過比較應用程式不同版本之間的延遲分佈,自動識別效能衰退(regressions)。
2. Cloud Profiler (持續剖析)
Cloud Profiler 是一個統計性的、低開銷的剖析器,可持續從你的生產環境應用程式收集 CPU 使用情況和記憶體分配資訊。
- Wall Time vs. CPU Time: Wall time 是花費的總時間;CPU time 是處理器實際工作的時間。
- 火焰圖 (Flame Graphs): 一種可視化工具,用於查看哪些函式消耗了最多的資源。
- 低開銷: 設計用於在生產環境運行,通常對 CPU/記憶體的影響小於 5%。
3. 合成監控 (Synthetic Monitoring)
合成監控涉及創建自動化腳本來模擬使用者行為(例如:登入、將商品加入購物車),以測試應用程式在各個全球位置的可用性和效能。
- 主動性: 在真實使用者發現問題之前找到問題。
- 基準: 為關鍵使用者旅程建立效能基準。
識別效能瓶頸
Professional Cloud Architect 必須能夠觀察 Trace 或 Profile 並識別「原因」:
- N+1 查詢問題: 在 Cloud Trace 中,你會看到幾十個小的、連續的資料庫 Span,而不是一個大的批次 Span。
- 執行緒爭用 (Thread Contention): 在 Cloud Profiler 中,你會看到許多函式正在等待鎖定 (lock) 或同步。
- 記憶體洩漏 (Memory Leaks): 在 Cloud Profiler(堆積剖析 Heap Profile)中,你會看到記憶體使用量隨時間穩定增長而未被釋放。
架構師洞察: 在考試中,如果場景詢問如何在不停止服務的情況下,找到生產環境中導致高 CPU 的具體程式碼行或函式,答案幾乎總是 Cloud Profiler。如果詢問如何找到鏈條中哪個微服務導致了延遲,答案則是 Cloud Trace。 ::
FAQ — 應用程式效能管理
Q1. Cloud Trace 是否需要修改程式碼?
是的,通常需要。雖然某些環境(如 App Engine)有內建支持,但大多數應用程式需要使用 OpenTelemetry SDK 或 Cloud Trace 用戶端程式庫來生成並發送 Span。
Q2. Cloud Profiler 在生產環境使用安全嗎?
是的。它使用統計採樣,對效能的影響微乎其微(通常 < 5%)。這讓你能夠找到僅在生產負載下出現的「海森堡 Bug (Heisenbugs)」。
Q3. 「堆積剖析 (Heap Profiling)」與「CPU 剖析 (CPU Profiling)」有什麼區別?
CPU 剖析 識別哪些函式使用了最多的處理器時間。堆積剖析 識別哪些函式分配了最多的記憶體,以及哪些對象留在記憶體中(潛在的洩漏)。
Q4. 如何使用 APM 分析資料庫查詢效能?
使用 Cloud Trace 查看單個查詢的延遲。對於 Cloud SQL 的更深層分析,請使用 Query Insights,它為慢速查詢及其對系統效能的影響提供了專用儀表板。
Q5. 什麼是「真實使用者監控」(Real User Monitoring, RUM)?
RUM 捕捉來自實際使用者瀏覽器或行動裝置的效能數據。當 Cloud Trace 處理後端時,RUM(通常透過 Firebase Performance Monitoring 或第三方工具實現)會告訴你頁面在使用者螢幕上實際渲染花了多長時間。
Cloud Trace 深入剖析 — 採樣、保留與配額
Cloud Trace 不只是一個漂亮的瀑布圖;理解它的資料平面對於架構師規劃可觀測性預算至關重要。
資料擷取與採樣
- 預設代理採樣: Cloud Trace 代理(OpenTelemetry、OpenCensus)通常每個執行個體預設採樣率為 0.1 QPS,以將開銷降到最低。你可以用
ProbabilitySampler或ParentBased採樣器覆寫。 - Head-based 對比 Tail-based: Cloud Trace 本身是 head-based(在請求開始時決定)。若要做 tail-based 採樣(只保留慢請求或錯誤 trace),必須在 Cloud Trace 前面架一個 OpenTelemetry Collector,跑
tail_sampling處理器。 - 免費額度: 每個專案每月前 250 萬個 span 免費;超過後依每百萬 span 計費。
重要的 Span 屬性
一個良好標註的 span 會帶上:
http.method、http.status_code、http.route— 用於 API 關聯db.system、db.statement— 與 Cloud SQL Query Insights 做 SQL/NoSQL 關聯messaging.system、messaging.destination— 用於 Pub/Sub 延遲分析- 自訂的
user.tier或tenant.id標籤,用於依客戶分群切分延遲
分析報告與洞察
Analysis Reports 功能讓你比較兩個時間窗口或兩個服務版本之間的延遲分佈。這是驗證 Cloud Run revision 推上線後是否引入回歸的標準方式。報告以可設定的百分位(p50/p95/p99)計算,並標示出延遲偏移最大的 span。
保留期
Trace 保留 30 天。如果需要更長的延遲分析(例如季度容量規劃),透過 Cloud Trace API 匯出 trace 資料,或用排程匯出工作 sink 到 BigQuery,然後在 Looker Studio 上建構歷史 p95/p99 趨勢儀表板。
PCA 考試請記住:Cloud Trace 保留期是 30 天,免費額度是每月 250 萬 span。如果情境問到年度延遲趨勢分析或法遵歸檔,正確答案是透過 Cloud Trace API 匯出到 BigQuery — 而不是「調高 Cloud Trace 保留期」,那不是一個可設定的選項。
Cloud Profiler — CPU、Heap 與爭用 Profile
Cloud Profiler 支援五種 profile 類型,PCA 考試經常測試該選哪一種。
Profile 類型
| Profile | 量測項目 | 適用情境 |
|---|---|---|
| CPU time | 函式佔用 CPU 的時間 | 熱點迴圈、低效演算法 |
| Heap | 存活的記憶體配置 | 記憶體洩漏、過大快取 |
| Allocated heap | 配置過的總位元組數(含已釋放) | GC 壓力分析 |
| Contention | 執行緒等待 mutex 的時間 | 鎖爭用、序列化臨界區 |
| Threads | goroutine / thread 數量 | Go 服務的 goroutine 洩漏 |
語言支援
- Go — 透過
cloud.google.com/go/profiler完整支援所有五種 profile - Java — CPU、heap、contention,透過 Java agent JAR(
-agentpath:/opt/cprof/profiler_java_agent.so) - Node.js — CPU 與 heap,透過
@google-cloud/profiler - Python — CPU 與 wall-time,透過
google-cloud-profiler套件 - C++ — CPU 與 heap,透過基於 perftools 的代理
部署模式
在 GKE 上,通常把 profiler 代理打進容器映像,並要求工作負載身分擁有 roles/cloudprofiler.agent。在 Cloud Run 上,只要設定 GOOGLE_CLOUD_PROFILER_ENABLE=true 環境變數並引入 SDK,Go 與 Java 會自動啟用 profiler;第一代 Cloud Run 在某些 base image 上不支援 Java agent 的 attach 機制,請在 staging 測試。
解讀火焰圖
寬度 = self time。顏色依套件決定(決定性,不代表嚴重程度)。點任一 frame 可以 focus,讓圖以該 frame 為新的根重畫 — 這對於聚焦某個函式庫內部的熱路徑非常有用。用 「diff」檢視比較兩個時間範圍,可以確認優化是否真的有效。
PCA 考試會清楚區分 Cloud Trace(請求鏈中哪個微服務慢)與 Cloud Profiler(單一服務中哪個函式慢)。如果題目問的是哪一個具體程式碼行在生產環境燒 CPU 或洩漏記憶體、且要求對效能影響極小,答案永遠是 Cloud Profiler 搭配對應的 profile 類型 — CPU profile 抓熱程式碼、heap profile 抓存活洩漏、allocated-heap 抓 GC 壓力、contention 抓鎖等待。選錯 profile 類型是常見的混淆選項。
延遲百分位、SLO 與 Apdex
「平均延遲」是個謊言;PCA 情境會逼你用百分位思考。
為什麼 p50 會騙人
若 99% 的請求在 80ms 完成,1% 在 8 秒,平均值是 ~160ms,但使用者體驗是雙峰分布。Cloud Monitoring 的分布類型指標(type: DISTRIBUTION)保留了 histogram,所以你可以在 p50、p95、p99、p99.9 之間切換而不需要重新埋點。
在 Cloud Monitoring 定義 SLO
Cloud Monitoring 的 Service Monitoring UI 讓你對服務宣告 SLO:
- SLI 類型: request-based(good_requests / total_requests)或 windows-based
- 目標: 例如 28 天滾動窗口內 99.5% 的請求 < 300ms
- 錯誤預算: 自動推導;當預算燃燒速度超過閾值時,burn-rate 告警會觸發
Apdex (Application Performance Index)
Apdex 是一個 0–1 的單一分數,由目標延遲 T 推導:
- Satisfied: 回應時間 ≤ T
- Tolerating: T < 回應時間 ≤ 4T
- Frustrated: 回應時間 > 4T
- Apdex = (satisfied + tolerating/2) / total
Cloud Monitoring 不直接呈現 Apdex,但可以用 MQL 查詢針對分布指標計算。許多團隊在主管儀表板上呈現 Apdex,因為它把延遲、錯誤率、長尾行為壓縮成一個非工程人員也能行動的數字。
常見考試陷阱:情境說「平均延遲遠在 SLO 內,但客戶在抱怨」。正確診斷是去看 Cloud Trace 與 Cloud Monitoring 分布指標的 p95/p99,而不是加機器。長尾延遲對平均值是隱形的,若原因是 GC 暫停或鎖爭用,加 instance 通常沒用。
用 OpenTelemetry 做分散式追蹤 — 上下文傳播
OpenTelemetry (OTel) 現在是埋點 Cloud Trace 的官方建議;舊的 OpenCensus SDK 已進入維護模式。
傳播格式
跨服務邊界攜帶 trace 上下文的 wire format 決定了你的 trace 是否能連起來:
- W3C Trace Context(
traceparent、tracestate標頭)— 現代預設,GCP、AWS X-Ray 與多數廠商採用 - B3(單標頭
b3或多標頭X-B3-TraceId)— Zipkin 與 Istio service mesh 採用 - Google Cloud 格式(
X-Cloud-Trace-Context)— GCP 負載平衡器與 Cloud Run 入口發出
設定 Propagator
在 Go 中設定 otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}, gcppropagator.CloudTraceOneWayPropagator{})),讓 W3C 與 GCP 兩種格式都能接收與發出。漏掉 GCP propagator 是「trace 斷掉」最常見的原因 — Cloud Load Balancer span 與應用 span 會出現在兩個分離的 trace 裡。
Exporter 選項
- 直接 exporter:
googlecloudexporter 把 span 直接推到 Cloud Trace API。簡單,但沒有緩衝。 - OTel Collector: 跑 sidecar 或 gateway collector,搭配
googlecloudexporter。提供批次、重試、tail sampling,以及 fan-out 到多個後端的能力(例如 Cloud Trace 加 Jaeger 給開發環境)。
自動埋點
Java agent(opentelemetry-javaagent.jar)與 Python(opentelemetry-instrument)對 HTTP server、JDBC、Redis、Kafka、gRPC client 提供零程式碼埋點。考試重點:知道自動埋點不寫程式就能拿到 80% 的價值 — 再針對商業關鍵操作手動加幾個 span 即可。
應用效能用的自訂指標
Cloud Trace 顯示延遲;Cloud Monitoring 自訂指標顯示吞吐量、queue 深度、快取命中率,以及任何領域訊號。
指標類型
- Gauge — 當前值(queue 深度、開啟的連線數)
- Cumulative — 單調遞增計數器(process 啟動以來服務的請求數)
- Delta — 回報區間內的變化量
寫入自訂指標
用 OpenTelemetry Metrics API 搭配 googlecloud exporter,或直接呼叫 monitoring.googleapis.com/v3/projects/{project}/timeSeries:create。最佳實踐:
- 基數紀律: 避免
user_id、request_id這類 label。把每個指標的 label 基數控制在 ~1000 以下;Cloud Monitoring 會拒絕超過配額的寫入。 - 資源類型: 永遠設定 monitored resource(例如
k8s_container、cloud_run_revision),讓圖表能依 pod 或 revision 切分。 - 命名慣例:
custom.googleapis.com/<service>/<metric_name>— 跨部署保持穩定。
有用的應用效能指標
app/request_queue_depth— 持續 > 0 代表你 CPU-boundapp/db_pool_utilization— > 80% 預示連線即將耗盡app/cache_hit_ratio— 下降通常伴隨下游延遲尖峰app/business_txn_duration— 端到端工作流 SLO 計算用的分布指標
基於自訂指標的告警
在 MQL(Monitoring Query Language)中把這些指標和內建指標組合起來;例如當 cpu_utilization > 70% 且 db_pool_utilization > 80% 持續 10 分鐘時告警,這代表真實的飽和事件而非短暫尖峰。
CI/CD 中的效能回歸偵測
在生產環境抓到 30ms 的延遲回歸代價昂貴;在 CI 抓到則是免費。
Pipeline 階段
- Microbenchmark — 在 Cloud Build 跑
go test -bench、JMH、pytest-benchmark;若任何 benchmark 比 Cloud Storage 中的基準回歸 > 5% 就讓 build 失敗。 - 負載測試階段 — 拉起暫時的 GKE namespace 或 Cloud Run revision;用獨立 Cloud Build worker pool 上的 k6 或 Locust 對它打流量;結果送進 BigQuery。
- Trace diff — 從負載測試擷取 trace 樣本,用 Cloud Trace Analysis Reports API 比較 p95 與上一個綠燈 build。
- Profile diff — 在負載測試期間錄 CPU profile,附
versionlabel 推到 Cloud Profiler,用 Profiler UI 的「diff」檢視(或寫 script 呼叫gcloud profiler)偵測新的熱路徑。
Cloud Deploy 金絲雀閘門
用 Cloud Deploy 可以掛一個自訂的 verify 步驟,呼叫 Cloud Function 查詢 Cloud Monitoring 中新 revision 的 p95 延遲。若 p95 超過閾值持續 5 分鐘,金絲雀會透過 gcloud deploy rollouts rollback 自動回滾。
合成監控作為閘門
對金絲雀 URL 跑合成監控,要求 X 次連續綠燈才推進到 100%。合成監控能抓到內部負載測試漏掉的「亞洲使用者 DNS 壞了」這類失敗模式。
便宜的回歸偵測:在部署後從一個對你金絲雀 URL 打的合成監控,每次發出一個 Cloud Monitoring 指標 deploy/golden_signal_p95。Cloud Deploy postdeploy hook 用一行查詢這個指標、回歸時 exit 非零,就能在不蓋專門的效能測試基礎設施下,得到一個自動化、近乎零成本的閘門。
JVM 與 GC 調校模式
GKE 與 Cloud Run 上的 Java 工作負載對 GC 敏感;PCA 考試不會要你設 -XX:MaxGCPauseMillis,但會期待你知道哪個 collector 配哪種工作負載。
Collector 選擇
- G1GC(JDK 11+ 預設)— 均衡;適合 4–32 GB 的 heap;透過
-XX:MaxGCPauseMillis=200提供可預測的暫停時間 - ZGC(JDK 15 起 production)— 次毫秒暫停;適合低延遲 API;支援 < 1 GB 到 16 TB 的 heap
- Shenandoah — 類似 ZGC;OpenJDK 替代方案,Red Hat build 常見
- Parallel GC — 吞吐優先;適合 Dataproc 上的批次工作
容器感知設定
在 GKE 上永遠設定 -XX:+UseContainerSupport(JDK 10 起預設),並用 -XX:MaxRAMPercentage=75.0 取代 -Xmx,讓 JVM 隨容器記憶體限制自動調整 heap。寫死 -Xmx 在你調整 pod 大小時會導致 OOMKilled。
用 Cloud Profiler 診斷 GC
Cloud Profiler 的 allocated heap profile 指出產生配置壓力的呼叫點。搭配 JFR (Java Flight Recorder) 匯出做完整的 GC 事件分析。典型症狀:p99 延遲尖峰對齊 Cloud Profiler CPU profile 中週期性的平坦線 — 那些平坦線就是 stop-the-world 暫停。
Cloud Run 特殊考量
Cloud Run gen2 支援 JVM,但冷啟動代價主要在 class loading。在映像裡用 CDS (Class Data Sharing) 搭配 -XX:ArchiveClassesAtExit=/tmp/app-cds.jsa,或用 GraalVM 加 Spring Native / Quarkus 編譯成原生映像,達到次秒級冷啟動。
JVM-on-GCP 速查表:G1GC 給一般 HTTP 服務、ZGC 給低延遲 API、Parallel 給 Dataproc 批次工作。容器內永遠用 -XX:MaxRAMPercentage(而非 -Xmx)。Cloud Run 冷啟動優先選 GraalVM 原生映像而非 JIT 調校。Cloud Profiler 的 allocated heap profile(不是「heap」)才是 GC 壓力分析的正確檢視。
用 Firebase Performance Monitoring 做前端 RUM
後端 p95 很好,但使用者看到的是整個頁面載入 — DNS、TLS、JS parse、render。Firebase Performance Monitoring (FPM) 補上這塊。
Web SDK
firebase/performance 提供 JS SDK,自動擷取:
- First Input Delay (FID) 與 Interaction to Next Paint (INP) — 2024 年取代 FID 的新 Core Web Vital
- Largest Contentful Paint (LCP) — 視覺完成度
- Cumulative Layout Shift (CLS) — 視覺穩定度
- HTTP/S 網路請求 — 時長、payload 大小、回應碼
行動 SDK (Android / iOS)
行動 SDK 額外提供 app start time(啟動到第一幀的時間)與畫面渲染(凍結幀 > 700ms、慢幀 > 16ms),不需手動埋點。
自訂 Trace
import { trace } from "firebase/performance";
const t = trace(perf, "checkout_submit");
t.start();
await submitCheckout();
t.stop();
自訂 trace 讓你從使用者裝置端到端量測商業意義操作(結帳送出、搜尋回應),包括網路往返。
將 RUM 與 Cloud Trace 縫合
在前端 fetch 呼叫中注入 W3C traceparent 標頭(Firebase SDK 預設不會做,必須自己加)。後端 Cloud Trace span 會連到同一個 trace ID,給你從「使用者點按鈕」貫穿 CDN、負載平衡器、微服務、資料庫的單一瀑布圖。
資料管線
Firebase Performance Monitoring 資料進到 Firebase console,保留 90 天。透過 Firebase BigQuery 匯出整合到 BigQuery,可以無限保留、與營收表 join、做 cohort 分析(例如「這次部署有沒有讓 Android Chrome 120 的使用者結帳變慢?」)。
採樣與配額
FPM 對自動與自訂 trace 都做採樣;web 端的採樣率是動態的且不可由使用者設定。對高流量應用,設計儀表板時用 count-weighted 百分位,讓採樣後的指標仍能反映完整母體。