你的服務有監控。CPU、記憶體、磁碟、QPS、錯誤率,Grafana 上二十幾張圖,全部是綠的。然後客服轉來一則訊息:「我從剛剛就一直付款失敗。」
這一幕幾乎每個做過線上系統的人都遇過。而它揭露的問題不是「監控做得不夠多」—— 是監控這件事本身,只能回答你事先想得到的問題。
可觀測性要處理的正是這一類問題:那些你事前沒想到、事後又必須立刻回答的問題。
這一章不談工具,先把觀點建立起來:
這一軌的工具主線是 Prometheus + Grafana + OpenTelemetry。如果你熟悉的是 CloudWatch(AWS ch11 講過它的考點),概念大多是相通的——這裡談的是方法論,不是某一家的操作介面。
另外,資料庫效能與維運 ch07 講過資料庫層的排查流程。這一軌是系統與服務層的版本,而且要處理一個 ch07 迴避掉的問題:當你連「該查哪個服務」都不知道的時候,從哪裡開始。
「監控」和「可觀測性」常被當成同義詞換著用,但它們回答的是兩種形狀完全不同的問題。分清楚這件事,才知道為什麼多加二十張儀表板救不了你。
監控的運作方式是:你先想到一個可能出錯的地方,然後為它做一個指標和一條告警。
「CPU 會不會滿?」 → 收 CPU 使用率 + 告警 > 80%
「服務會不會噴 500?」 → 收錯誤率 + 告警 > 1%
「磁碟會不會滿?」 → 收使用率 + 告警 > 90%這些都是已知的未知(known unknowns):你知道這件事可能發生,只是不知道何時發生。監控在這一類問題上非常有效,而且應該做好。
這是未知的未知(unknown unknowns)。它的形狀長這樣:
「為什麼只有使用某張特定銀行卡、金額超過三萬、
又剛好被導到新版風控的那批請求會失敗?」沒有任何一張事先做好的儀表板會有這個維度組合。而如果你的回答是「我加個 log 再上線一次看看」,那就代表你的系統在這個問題上是不可觀測的——因為你必須改程式才能提問。
可觀測性不是「收集更多資料」。無差別地把所有東西都收起來,只會得到一堆昂貴又查不動的資料(這一章最後會算這筆帳)。它的關鍵是「維度」與「可關聯性」:資料裡有沒有足夠的維度讓你切分,以及不同來源的資料能不能串成一條線索(這是這一軌的第三條主線,本章倒數第二節會展開)。
三本柱人人會背,但真正該記的不是「它們各是什麼」,而是它們的成本隨著什麼東西成長——因為這決定了什麼資訊該放哪一邊。
| 回答什麼 | 成本隨什麼成長 | |
|---|---|---|
| Metrics | 「有沒有問題、多嚴重、趨勢如何」 | 時序條數(維度組合的乘積),與請求量幾乎無關 |
| Logs | 「當時到底發生了什麼細節」 | 事件筆數 × 每筆大小,與請求量成正比 |
| Traces | 「這一次請求的時間花在哪一段」 | span 數 × 取樣率,與請求量成正比 |
一個指標記錄的是「數值隨時間的變化」。它已經被聚合過了:一億次請求和一千次請求,只要維度組合一樣,儲存成本幾乎相同。
日誌保留了完整的上下文,是最靈活的一種。代價是它與流量成正比:QPS 翻倍,日誌帳單就翻倍。所以日誌的核心問題永遠是「記什麼、記多久、怎麼取樣」(ch04 專講)。
在單體服務裡,一句慢 SQL 用 db ch01 的方法就能查。但在五個服務串起來的鏈路裡,「這個請求花了 3 秒」這件事,metrics 只會告訴你每個服務各自的延遲分佈——它沒辦法告訴你這一次的 3 秒是在哪一跳被吃掉的。那是 trace 存在的唯一理由(ch05 專講)。
同一套系統,可以從兩個位置觀察,而它們會給出不同的答案——當兩者矛盾時,永遠相信外面那個。
這是這一軌後面(ch06)會反覆用到的一條原則:
❌ 「應用程式回傳 5xx 的比例 < 0.1%」
—— 請求沒進來的時候,這個數字永遠漂亮
✅ 「從使用者的位置量,付款請求在 2 秒內成功完成的比例 > 99.9%」
—— 不管卡在哪一層,只要使用者做不到,它就算失敗這也是這一軌的第二條主線:症狀優先於原因。SLI 與告警都要從「使用者感受到什麼」出發,而不是從「機器上有哪些數字可以收」出發。機器指標是拿來找原因的,不是拿來定義「好不好」的。
「我該收哪些指標?」這個問題有三套現成答案,它們不是競爭關係,而是分別對應不同的觀測對象。
Rate(每秒請求)、Errors(錯誤率)、Duration(延遲分佈)。等於黃金訊號拿掉飽和度,最適合微服務與 API:每個服務都用同一組三個指標,儀表板長得一模一樣,換服務不用重新學怎麼看。
Utilization(使用率)、Saturation(飽和/排隊)、Errors(錯誤)。適用於 CPU、記憶體、磁碟、網路卡、還有連線池與執行緒池。
Threads_running 也是同一個概念的資料庫版本。對外的 API/每個微服務 → RED(+飽和度)
機器、連線池、執行緒池、佇列 → USE
面向使用者的關鍵旅程 → 黑箱探針 + 之後的 SLI(ch06)先把 RED 舖滿所有服務,再對關鍵資源補 USE。這兩層蓋完,大部分「有沒有事」的問題就答得出來了——剩下的「為什麼」交給 trace 與 log。
如果要選一個「害最多人誤判」的東西,那就是平均值。而它幾乎是所有預設儀表板的預設選項。
1000 次請求:
970 次 → 50 毫秒
30 次 → 30 秒(逾時)
平均回應時間 = (970×0.05 + 30×30) / 1000 ≈ 0.95 秒儀表板上顯示「平均 950 毫秒」,看起來只是有點慢。但真實情況是每 33 個使用者就有一個完全用不了。
就算你看了 p99,仍然可能被騙。當系統有兩種以上的行為模式時,分位數會混在一起:
快取命中的請求: 5 毫秒(佔 90%)
快取沒中的請求:800 毫秒(佔 10%)
p50 = 5ms、p95 ≈ 800ms —— 中間那段其實不存在任何請求看到 p50 和 p99 差距極大時,不要想「怎麼把 p99 壓下來」,要先想「是不是有兩群不同的請求被混在一起量了」。正確的做法是拆維度(依端點、依快取命中與否、依客戶類型分開量)——這正是第一節說的「維度」為什麼是可觀測性的關鍵。
週五晚上八點,客服累積了十幾則「付款一直失敗」的訊息。而工程團隊看到的是:
先做唯一能繞過所有內部指標的事:用使用者的身分,從外面走一次那條路徑。
SSL handshake failed。/health 回 200,而它走的是內網、不經過那張憑證。/health,而是真的走一遍關鍵旅程。很多團隊三樣都有了,卻還是查不動問題。原因通常不是資料不夠,而是三份資料之間沒有橋——每次排查都要在三個系統之間靠人腦與複製貼上接力。
trace_id 去撈風控服務的日誌,看到「重試三次、每次逾時 900ms」。到這裡根因就明確了。trace_id 與 span_id。這是最重要的一條,而在 Spring 專案裡它幾乎是免費的(ch05/ch08 會做)。service.name、env、version 要用同一套命名(OpenTelemetry 的 semantic conventions 就是在做這件事,ch05 講)。否則你會在 metrics 裡叫 payment-svc、在 log 裡叫 payment,然後無法自動關聯。不要從「有哪些指標可以收」開始——那會得到一堆沒人看的儀表板。從使用者做的事情往回推:
① 列出關鍵旅程:登入、瀏覽商品、下單、付款、查訂單
② 每條旅程定義「成功」是什麼(含時間上限) → 未來的 SLI(ch06)
③ 為每條旅程做黑箱探針 → 「壞了沒」
④ 沿著旅程經過的每個服務舖 RED → 「壞在哪一段」
⑤ 對關鍵資源補 USE → 「為什麼壞」
⑥ 把 trace_id 串起來 → 讓上面四層可以互相導航這個順序的好處是:每一步都對應一個真實的問題,而不是對應一個工具的功能清單。
這一章講了很多「應該要有」的東西。這一節講它們的帳單——因為可觀測性系統很容易變成整個架構裡最貴的一套系統(ch08 會把這筆帳完整算一次)。
下一章進入實作:Prometheus 的資料模型只有一句話,但那句話決定了它會不會在某天早上把你的記憶體吃光。
| 監控 | 可觀測性 | |
|---|---|---|
| 回答哪種問題 | 已知的未知——你想得到會出錯的地方 | 未知的未知——你昨天沒想到的問題 |
| 運作方式 | 事先定義指標與告警門檻 | 保留足夠維度,事後任意切分查詢 |
| 判準 | 「這個情況會不會通知我」 | 「要不要重新部署才能提問」 |
| 產出 | 告警——影響 MTTD(多快發現) | 回答問題的能力——影響 MTTR(多快修好) |
| 先做哪個 | 先做這個:連有事都不知道時,能問任意問題也沒用 | 有了告警之後才顯出價值 |
| Metrics | Logs | Traces | |
|---|---|---|---|
| 回答 | 有沒有問題、多嚴重、趨勢 | 當時的細節 | 這一次請求時間花在哪一段 |
| 成本隨什麼長 | 時序條數=維度組合的乘積 | 事件筆數 × 每筆大小 | span 數 × 取樣率 |
| 與流量的關係 | 幾乎無關(已聚合) | 成正比 | 成正比 |
| 適合放高基數資訊嗎 | 絕對不要(乘法) | 適合(加法) | 適合(加法) |
| 適合告警嗎 | 適合——便宜、可長期保留 | 少數情況(特定錯誤字串) | 不適合,是排查工具 |
| 排查順序 | ① 發現異常 | ③ 確認細節 | ② 定位到哪一段 |
| 框架 | 內容 | 用在什麼上 | 重點 |
|---|---|---|---|
| 四個黃金訊號 | 延遲、流量、錯誤、飽和度 | 面向服務的綜合檢查 | 飽和度最常被忽略,卻是唯一有預測性的 |
| RED | Rate、Errors、Duration | 請求驅動的服務、微服務、API | 每個服務同一組指標,儀表板可複用 |
| USE | Utilization、Saturation、Errors | CPU/記憶體/磁碟/連線池/執行緒池 | 使用率滿不一定有事,有人排隊才是問題 |
| 黑箱探針 | 從外部走完整旅程 | 關鍵使用者旅程 | 唯一能證明「使用者現在能用」的東西 |
點擊卡片翻面查看答案,共 13 張。