大綱

  • SLI 設計起點:user-journey 而非 system metric
  • 量測點選擇:edge / gateway / service / dependency 各自代表什麼
  • Ratio metric vs latency percentile:何時用哪種
  • Burn rate 訊號:multi-window multi-burn-rate alert
  • Error budget 計算所需的 metric 結構
  • 4.2 metrics 的分工:4.2 是 counter/gauge/histogram 基礎、4.6 是 SLI 化的設計
  • 4.4 dashboard-alert 的分工:4.4 是 alert 規則治理、4.6 是 alert 的訊號源頭
  • 反模式

概念定位

SLI 訊號設計是把可靠性目標轉成可量測資料的步驟,責任是讓 SLO 政策建立在使用者旅程與服務結果上。

CPU、memory、queue depth 可以提供系統背景,但 SLI 需要回答的是使用者層面的問題:request 是否成功、回應是否夠快、結果是否正確。SLI 量測的位置跟算式決定了 SLO 反映的是「使用者體驗」還是「基礎設施健康」— 兩者的判讀意義不同。

本章處理的是 metric 到 SLI 的轉換。4.2 定義 counter / gauge / histogram 的基礎型別;本章定義怎麼用這些型別組出代表使用者體驗的 SLI,並設計 burn rate alert 的訊號結構。SLO 政策本身(error budget freeze、release gate 決策)由 6.6 SLO 政策 處理。

SLI 設計起點:User Journey

從使用者操作推導 SLI

SLI 的設計起點是「使用者在做什麼、期待什麼結果」,不是「系統有什麼 metric 可以用」。

一個 checkout 流程的使用者期待:request 成功(不會看到 error page)、回應夠快(不會等超過 3 秒)、結果正確(扣款金額正確)。對應三種 SLI:

  • Availability SLI:成功 request 的比例(successful_requests / total_requests
  • Latency SLI:回應時間在閾值內的比例(requests_under_3s / total_requests
  • Correctness SLI:結果正確的比例(需要業務邏輯判定,通常用特定 error code 或 reconciliation 結果)

每個 user journey 不需要三種 SLI 都有。Checkout 的 availability 跟 latency 是核心;correctness 靠事後對帳驗證。搜尋頁面的 latency 比 availability 更關鍵 — 使用者容忍偶發的「搜不到結果」但不容忍 5 秒的載入。

System metric 跟 SLI 的差異

CPU > 90% 不是 SLI — 它是 cause signal。CPU 高但 latency 正常,使用者沒受影響。Disk usage > 85% 也不是 SLI — 它是 capacity signal,需要處理但不代表當下使用者體驗退化。

System metric 的價值在 root cause analysis,不在 SLI。事故中先看 SLI 判斷「使用者是否受影響」,確認受影響後再看 system metric 判斷「原因是什麼」。把 system metric 當 SLI 會讓 SLO 反映基礎設施噪音而非使用者體驗。

量測點選擇

SLI 的量測點影響「看到的是誰的觀點」。同一個 request 在不同位置量測會得到不同的 latency 跟 success rate。

Edge / Load Balancer

最貼近使用者的量測點。量到的 latency 包含 network round-trip + TLS handshake + 所有 backend 處理時間。Availability 反映的是使用者實際看到的 success rate(包含 load balancer 自身的 502/503)。

優點是最能代表使用者體驗。缺點是 load balancer 的 metric 粒度有限 — 通常只有 status code 跟 latency,不帶 service-level 的維度切分。

API Gateway

比 edge 更有應用層上下文。可以按 route / method / tenant 切分 SLI。量到的 latency 不含 network round-trip(已經進入服務網路),但包含 authentication、rate limiting 跟所有下游處理。

API gateway 是多數團隊的 SLI 量測起點 — 粒度足夠、位置夠近使用者、通常已有 instrumentation。

Service level

每個服務的 handler-level metric。可以看到單一服務的 latency 跟 error rate,但不含上下游的影響。適合做 service-level SLO(「order service 的 p99 latency < 200ms」),但不直接代表 user-journey SLO。

Service-level SLI 的價值在於 SLO 階層化 — user-journey SLO 拆分成每個服務的 SLO,事故時能快速定位是哪個服務的 SLO 被打破。

Dependency level

量測外部依賴(database、cache、third-party API)的回應時間跟 error rate。Dependency metric 的角色是 SLI 退化時的歸因訊號,用來追溯因果鏈而非直接代表使用者體驗。Database latency 上升 → service latency 上升 → user-journey latency SLO 被打破 — dependency metric 幫助追溯因果鏈。

SLI 的 Metric 結構

Ratio metric:availability 跟 correctness

Availability SLI 的 metric 結構需要兩個 counter:total requests 跟 successful requests(或 failed requests)。SLI = good / total。

1# Availability SLI
2http_requests_total{service="checkout", status="2xx"} / http_requests_total{service="checkout"}

定義「good」的邊界需要明確。5xx 算 bad,4xx 呢?Client error(400)通常不算服務失敗;authentication failure(401/403)也不算。但 429(rate limit)可能代表服務容量不足,視情境可能算 bad。這個邊界要在 SLI 定義時明確寫下來。

Latency metric:threshold-based ratio

Latency SLI 用 histogram 量測,SLI 值是「在閾值內的 request 比例」。

1# Latency SLI:p99 < 500ms 的比例
2histogram_quantile(0.99, rate(http_request_duration_seconds_bucket{service="checkout"}[5m])) < 0.5
3
4# 或用 ratio 形式
5sum(rate(http_request_duration_seconds_bucket{le="0.5",service="checkout"}[5m]))
6/ sum(rate(http_request_duration_seconds_count{service="checkout"}[5m]))

Latency 閾值的選擇要對齊使用者期待而非系統能力。使用者期待 checkout 在 3 秒內完成 — 這是閾值的來源,不是「系統平均 latency 是 200ms 所以閾值設 500ms」。

Label 設計

SLI metric 的 label 需要足夠的切分能力(by service、by endpoint、by tenant),但受 cardinality 預算約束。

最小 label set:service name + method(GET/POST)+ status class(2xx/4xx/5xx)。這組 label 支撐 service-level SLO 計算。

擴展 label:endpoint path(normalize 後,例如 /api/orders/{id}/api/orders/:id)、tenant(多租戶場景)。每增加一個 label 維度,series 數量乘法增長 — 在 4.7 cardinality 的 label 白名單中管理。

Burn Rate 與 Multi-window Alert

Burn rate 的概念

Burn rate 是「error budget 被消耗的速度」。Burn rate = 1 代表按 SLO 允許的速度正常消耗;burn rate = 10 代表消耗速度是允許值的 10 倍 — 如果持續下去,error budget 會在 SLO 週期的 1/10 內耗盡。

用 burn rate alert 取代固定閾值 alert 的好處:burn rate 自動適應流量。低流量時段的幾筆 error 可能 burn rate 很低(因為 total 也少、對 error budget 影響小);高流量時段的相同 error rate 可能 burn rate 很高(因為 total 多、影響的使用者量大)。

Multi-window multi-burn-rate

單一時間窗口的 burn rate alert 會太吵(短窗口)或太晚(長窗口)。Multi-window 策略組合兩者:

視窗組合Burn rate 閾值偵測速度用途
5min + 1hr14.4x急性問題、page
30min + 6hr6x持續退化
2hr + 3day1x慢性消耗

14.4x 的來源:若 SLO 週期是 30 天、要在 1 小時內偵測到會耗盡 2% error budget 的問題,burn rate = (30 × 24) / 1 × 0.02 ≈ 14.4。6x 跟 1x 依此邏輯調整消耗比例跟偵測窗口。

短窗口(5min)抓急性:error rate 突然飆高、burn rate 衝到 14.4x。長窗口(1hr)做確認:退化確實持續、排除瞬間 spike。兩個窗口都超過閾值才觸發 alert,減少單一 spike 的 false alarm。

Recording rule 支撐 burn rate 計算

Burn rate 的計算涉及多個時間窗口的 ratio metric。每次 alert evaluate 都重算會給 TSDB 帶來查詢壓力。用 recording rule 把每個窗口的 error ratio 預計算,alert rule 讀 recording rule 的輸出:

1# Recording rule:5 分鐘窗口的 error ratio
2- record: slo:checkout:error_ratio:rate5m
3  expr: sum(rate(http_requests_total{service="checkout",status=~"5.."}[5m]))
4      / sum(rate(http_requests_total{service="checkout"}[5m]))

Alert rule 讀 recording rule 比每次重算 raw series 高效,也讓 burn rate 的計算邏輯集中管理。

Error Budget 的 Metric 結構

Error budget 是 SLO 週期內允許的錯誤量。SLO = 99.9% 代表 30 天內允許 0.1% 的 request 失敗。Error budget = total requests × 0.001。

Error budget 的 metric 結構需要:

  • Total requests(rolling window):過去 30 天的 total request count
  • Failed requests(rolling window):過去 30 天的 failed request count
  • Budget consumed:failed / (total × (1 - SLO target))
  • Budget remaining:1 - budget consumed

Budget remaining 作為 dashboard panel 跟 release gate 的輸入 — 餘額低於閾值時 freeze deployment。這個計算的 rolling window 用 recording rule 維護,避免每次查詢掃描 30 天的 raw data。

核心判讀

判讀 SLI 設計時,先看量測點是否貼近使用者,再看算式是否能穩定支援 error budget。

重點訊號包括:

  • Edge / gateway / service / dependency 的量測點是否各自有清楚責任
  • Latency percentile 與 ratio metric 是否對應不同使用者體驗
  • Burn rate 是否使用多時間窗,避免太吵或太晚
  • SLI label 是否有足夠切分能力,同時受 cardinality 預算約束
  • Error budget 的 rolling window 是否用 recording rule 維護

判讀訊號

  • Alert 用 system metric(CPU / memory)而非 user-facing 訊號
  • Burn rate 只有單窗、噪音多或偵測太晚
  • SLI 計算用平均、不用 percentile
  • Error budget 算式分母不穩(流量低時誤觸發、高時稀釋)
  • SLI 量測點離使用者太遠(內部 service 而非 edge/gateway)
  • SLI 沒有定義「什麼算 good request」的邊界(4xx 算不算 bad)
  • Burn rate 計算每次重算 raw series、沒有 recording rule

反模式

反模式表面現象修正方向
System metric 當 SLICPU/memory alert 頻繁但使用者沒受影響改用 user-facing ratio / latency SLI
Burn rate 單窗短窗太吵或長窗太晚、alert 價值低組合 5min+1hr / 30min+6hr 多窗策略
SLI 用 average latencyTail latency 被掩蓋、p99 使用者體驗失真改用 histogram percentile
Good request 邊界不明4xx 算不算 bad、SLI 值忽高忽低明確定義 good/bad 分類、寫進 SLI spec
Error budget 無 rolling月初 budget 就耗盡、剩下 20 天沒有保護機制用 rolling window 持續計算、預警消耗速度
SLI label 無界每個 URL path 都是獨立 SLI、series 爆炸Normalize path、label 白名單、cardinality 預算
SLO 無 owner沒人維護 SLI 定義跟閾值、退化時無人負責每個 SLO 帶 owner、定期審視

交接路由