iT邦幫忙

2026 iThome 鐵人賽

DAY 3
0
AI Engineering

Learning SRE for the AI Era:從 SRE Lab 到 Production AI Reliability系列 第 10 篇

Day 09|什麼是一個 Service?先畫出邊界,才知道故障影響哪裡

  • 分享至 

  • xImage
  •  

GitHub:darkstar1227/learning-sre-for-ai-era

**先講結論:**Service 是為使用者完成一項工作所需的系統邊界,也包含對結果、依賴與失敗行為的責任。

Day 8 把 AI 系統的 Reliability、Quality、Safety 分開看。接下來要談 failure model,得先回答一個更基本的問題:故障發生時,我們口中的「服務」到底是哪一段?邊界沒畫清楚,SLO、on-call、告警和事後檢討都很容易各講各的。

① 從一條熟悉的請求開始

傳統 Web API 的圖通常長這樣:

Client
  ↓
API
  ├── DB
  └── External API
  ↓
Response

使用者看見的是「查詢訂單」或「新增預約」;實際上,API 可能要驗證身分、讀資料庫、呼叫付款或物流服務,才有辦法回應。

若把 Service 理解成「這個 API process 還活著」,很快會遇到盲點:process 正常、HTTP 200 也正常,資料庫可能已回傳舊資料,外部付款服務可能拒絕請求,或最後回覆的內容根本沒有完成使用者要做的事。

在 SRE 的語境裡,Service 要說清楚使用者要完成什麼工作、請求會穿過哪些依賴,以及依賴失敗時系統怎麼回應。

畫出邊界,是為了在 incident 發生時判斷使用者受影響的訊號與處理責任。

② Service 的邊界不是網路拓撲圖的外框

同一個元件可以同時出現在不同 Service 的邊界裡。

以「查詢訂單」為例,訂單 API 對 App 團隊是一個 Service;資料庫團隊提供的 PostgreSQL 也是另一個 Service;付款供應商則是外部 Service。它們有各自的使用者、契約與責任人,但一筆使用者請求會把它們串成一條路徑。

使用者要查訂單
  ↓
Order API ──讀取──→ PostgreSQL
  │
  └──查詢──→ Payment Provider

這裡有兩個容易混在一起的概念:

名稱 問的問題 例子
元件(component) 這是什麼程式、資料庫或基礎設施? order-api pod、PostgreSQL instance
Service 它替誰提供什麼能力,失敗時誰承擔結果? 「使用者能查到正確訂單狀態」

一個 Service 可由很多元件組成;一個元件也可能同時服務多條使用者流程。把兩者畫上等號,最常見的後果是只監測 container health,卻沒發現使用者已經查不到正確結果。

GitHub 在 2026 年 9 月的一次事故中,內部資料清理工作把權限資料庫主節點的連線數寫到用盡。當時唯一被監看的健康訊號是 replica 延遲,而 replica 延遲全程正常;安全機制沒有察覺主節點正在逼近極限,直到請求開始大量逾時。監測的元件「健康」,使用者能不能登入、建 issue 卻早已不健康。GitHub 事故報告

Google 的 SRE 書也把服務視為有使用者期待的行為,而非單一機器:SLI 與 SLO 要先從使用者在意的行為出發,再決定如何量測。Google SRE Book:Service Level Objectives

③ 依賴關係要畫到「無法完成工作」的位置

不是每個呼叫失敗都同樣嚴重。關鍵在於它對對外能力的影響。

Order API
  ├── PostgreSQL:訂單資料的必要依賴
  ├── Payment Provider:付款狀態的必要依賴
  └── Recommendation API:可選依賴,失敗時可省略推薦區塊

這三條箭頭看起來很像,行為卻不同:

  • PostgreSQL 無法讀取時,系統不能假裝訂單存在,應明確失敗或提供已知的受限讀取模式。
  • Payment Provider 逾時時,不能把「查不到」寫成「未付款」;可能要顯示暫時無法確認,或改由背景工作補查。
  • 推薦系統掛掉時,訂單頁仍可用,只是少了推薦商品。

dependency map 除了列名稱,也要寫下失敗時的預期行為與可觀測訊號。

依賴 為何需要 失敗時的預期行為 可觀測訊號
PostgreSQL 讀取訂單資料 回受控錯誤,不回傳猜測資料 query error、latency、資料庫連線狀態
Payment Provider 顯示付款狀態 明示狀態暫不可確認,排入補查 dependency timeout、補查 backlog
Recommendation API 推薦商品 降級為不顯示推薦 fallback rate、dependency error

「預期行為」要在設計階段寫進 dependency map,而非 incident 後才補上。若團隊沒有決定 fallback,程式通常會等到 timeout、丟 500,或回一份看似完整但其實不可信的資料。

④ AI workflow 的 Service path 更長

AI 應用常被包成一個 /ask endpoint,實際的服務路徑卻比傳統 API 長得多:

Client
  ↓
Gateway
  ↓
Prompt / Policy
  ↓
Retriever ──→ Vector DB
  ↓
Model ──→ LLM Provider
  ↓
Tool Executor ──→ Internal / External tools
  ↓
Validator
  ↓
Response

其中每一段都可能是另一個 Service,也可能是同一個團隊維護的元件。方塊數量不決定 Service boundary;是否要對契約與風險負責,才是判斷依據。

以公司差旅問答為例,使用者問「國際機票需要誰核准?」:

Question
  ↓
Retriever 找政策文件
  ↓
LLM 依文件產生答案與引用
  ↓
Validator 檢查引用是否允許、格式是否符合 contract
  ↓
Answer

這條路徑至少有四種不同的失敗:

發生位置 使用者可能看見的結果 不該草率下的結論
Retriever 找不到正確政策 「模型不會回答」
Vector DB 檢索逾時 「LLM provider 壞了」
LLM Provider 429、5xx 或 latency 增加 「RAG 的資料品質下降」
Validator 擋下不允許的引用或越權 action 「API 成功就代表任務成功」

Day 8 的三條軸在這裡仍然成立。Provider timeout 是 Reliability 問題;引用無關文件卻自信作答是 Quality 問題;Agent 嘗試執行未授權操作則是 Safety 問題。它們可能同時發生,也可能只發生其中一種。別把整條 workflow 壓成 success: true。

⑤ 外部供應商仍是 dependency

「模型 API 回 200」不等於 AI Service 完成工作。同樣地,「我們用的是外部模型」也不等於所有可靠性責任都能交出去。

團隊無法控制 LLM provider 的內部系統,仍可決定自己的呼叫方式與失敗策略。包含 timeout、可重試的錯誤、rate limit 預算、資料不足時的拒答,以及 provider 不可用時要降級還是停止服務。

外部依賴出問題時,修復並不總是只靠「等待對方恢復」。AWS 在 2021 年 12 月 us-east-1 事件中提到,內部網路受影響後,monitoring 與 deployment systems 也受影響,讓排查與修復在能見度降低的狀態下進行。AWS 的事件報告 監控、部署與身分驗證等 control plane 能力,同樣應出現在 dependency map;它們壞掉時,資料面可能還在處理部分流量,恢復能力卻已經變弱。

對 AI workflow 而言,還要額外問幾個問題:

  • LLM provider 遇到 rate limit 時,使用者得到的是明確的稍後再試,還是無限重試?
  • Retriever 沒有足夠 context 時,系統能否誠實拒答?
  • Tool executor 不可用時,Agent 會不會捏造「已完成」?
  • policy 或 validator 故障時,預設是 fail open 還是 fail closed?不同風險的答案不會一樣。

阻擋付款與顯示推薦商品的風險不同,故障預設值也應不同。把這個選擇寫下來,才能討論與測試。

⑥ 從使用者視角畫一條 critical path

複雜系統不需要第一天就畫出全公司的服務地圖。先挑一個使用者工作,畫出完成它所需的最短路徑。

使用者取得「有來源、符合權限」的差旅政策答案
  ↓
Gateway 接受並驗證請求
  ↓
Retriever 取回允許的政策文件
  ↓
LLM 產生可解析的回覆
  ↓
Validator 驗證來源與權限
  ↓
回傳答案或明確說明無法完成的原因

這條 critical path 讓量測有對象、告警有上下文,也能及早討論 provider 故障或資料不足時的降級方式。這些是產品與風險決策,不是 SRE 一個人替大家決定。

Google 也提醒,服務間的 production dependencies 會形成巢狀關係;上游服務的放置與效能要求,會受下游依賴限制。Google SRE Book:Developing Software for Complex Machines 這也是為什麼只看自己服務的 CPU、memory 或 container restart 次數,通常不足以判斷使用者路徑是否健康。

⑦ 先分清楚「看得到」與「量得到」

先畫出 Service boundary,再挑 SLI。不是所有 trace 裡看得到的欄位,都已經是能用來管理可靠性的訊號。

以 /ask 為例,下面幾種狀態都可能出現在 telemetry:

訊號 可以先量什麼 還不知道什麼
Gateway request rate、5xx、end-to-end latency 低延遲是否代表答案有用
Retriever retrieval latency、empty-result rate 找到的內容是否真的支持回答
LLM Provider timeout、429、token usage 模型輸出是否正確或安全
Validator block rate、format failure rate block 是精準攔截還是誤擋
Tool Executor execution success、denied action count 工具成功執行是否完成使用者任務

前一欄是可操作的候選 SLI;後一欄需要 golden dataset、抽樣 review 或任務完成證據,才能用於判定。缺少這些證據時,就標成 UNKNOWN,不要用一個方便取得的 proxy 假裝它已被量測。

retrieval latency 正常
            ≠
retrieved context 足以支持答案

tool execution success
            ≠
使用者任務已安全完成

可觀測性讓我們看見系統狀態;SLI 則是經過定義、能對應使用者期待並支撐決策的量測。Day 10 開始拆 failure 時,這個區別會很有用:有些訊號告訴我們哪裡壞了,有些訊號才告訴我們使用者是否真的受影響。

⑧ 不要把責任邊界誤寫成 blame boundary

畫出依賴,是為了讓每個 Service owner 清楚自己的契約、可觀測性與降級行為。

較好的分法是:每個 Service owner 對自己的契約、可觀測性和已知降級行為負責;使用它的團隊則對「把這個依賴放進使用者路徑後,自己的 Service 如何失敗」負責。兩邊都要做事。

例如 LLM provider 429 時,provider 負責恢復其服務;應用團隊仍要決定 retry policy、排隊上限、使用者訊息與是否切換備援。若每一層都只說「那是下游的問題」,最後使用者看到的只會是自己的問題。

這也是 Service boundary 能當共同語言的原因:產品能說清楚哪個使用者工作最重要;開發者能說清楚 contract;SRE 能把可用性、延遲、依賴與降級行為變成可觀察的訊號;安全或領域專家能界定哪些操作絕不能 fail open。

Google 的 SRE Book 也把這件事寫進制度:postmortem 的目的是釐清根因、訂出可執行的預防措施,並作為全公司的學習機會。Service boundary 與依賴責任要先畫清楚;否則事後檢討容易變成追究個人責任,系統問題反而沒有被修正。Google SRE Book:Postmortem Culture

⑨ DIY:替一個使用者工作畫 Service boundary

這個 DIY 不需要先寫程式。挑一個你現在的 API 或 AI workflow,花 20 分鐘把它畫成一條使用者路徑。這個練習要找出使用者要完成什麼,以及中間卡住時系統會怎樣。完整架構文件不在本次範圍。

Step 1:用一句話寫下對外能力

不要寫「RAG service」或「訂單 API」。試著寫成使用者結果,例如:

已登入的員工可以查到有來源、符合權限的差旅政策答案。

這句話就是你暫時要守住的 Service contract。契約除了回傳文字,也要包含來源與權限。

Step 2:從 client 畫到 response

沿著一個 request 寫下它經過的元件。先畫最短路徑即可:

Client → Gateway → Retriever → Vector DB → LLM Provider → Validator → Response

每一個方塊旁邊補三個欄位:owner、必要或可選、失敗時的預期行為。若你寫不出最後一欄,不必硬湊答案,直接標 UNKNOWN。這表示失敗時的預期行為尚未定義。

Step 3:挑一個 dependency failure 預演

例如假設 LLM provider 回 429,依序回答:

  1. 使用者目前會看見什麼?
  2. 系統會重試、排隊、降級,還是直接拒絕?上限是什麼?
  3. 哪個 trace、log 或 metric 能告訴你這件事正在發生?
  4. 這是 Reliability、Quality、Safety 中的哪一條問題?是否需要 pager?

把答案寫進 dependency map。若答案是「不知道」,一樣保留。它比在 incident 當下才發現沒人知道更有用。

Step 4:找一個不能當 SLI 的訊號

從你的圖上挑一個容易量到、卻不能直接代表使用者結果的數字,例如 token usage、retrieval latency 或 tool execution success。替它寫下缺少的證據,再標為 UNKNOWN。這一步用來記錄 proxy 與使用者結果之間仍缺少的證據。

做完後,你應該能拿出一張含使用者結果、依賴、失敗預期與候選訊號的圖。這張圖記錄的是目前的設計假設。壓力測試與 incident drill 仍需另外進行;Day 10 分析 Fault → Error → Failure 時會以它作為共同座標。

⑩ 本文的概念驗收清單

這裡是讀者可自行完成的設計檢查。本文沒有建立 Day9/DIY、安裝依賴、啟動服務或執行以下檢查,因此不宣稱任何程式或架構已驗證。

  • [ ] 選出一項使用者可辨識的能力,並用一句話寫出它的 Service contract。
  • [ ] 從 client 到 response 畫出一條 critical path,而不只畫 deployment 元件。
  • [ ] 列出每個必要與可選依賴,包含 owner、失敗時的預期行為與可觀測訊號。
  • [ ] 對 AI workflow 分開標示 retriever、model、tool、validator 與 policy 的責任邊界。
  • [ ] 對至少一個 dependency failure 寫下 retry、fallback、拒絕或人工 review 的選擇與理由。
  • [ ] 確認 monitoring、deployment、authorization 等 control plane 能力是否也在 failure model 裡。
  • [ ] 把觀測到、但尚未能代表使用者結果的訊號標成 UNKNOWN,不把它直接當 SLI。

⑪ 本文結論

Service 是一項對外能力連同它的依賴與失敗行為。傳統系統的 API、DB 與外部服務如此;AI workflow 裡的 Retriever、LLM provider、Tool Executor、Validator 也一樣。

先畫出使用者的 critical path,再替每個依賴寫下失敗時的預期行為。下一次 timeout、錯誤答案或被阻擋的 action 出現時,這些邊界能幫助團隊判斷問題落在哪裡、接下來該問什麼。

Day 10 預告

有了 Service 與 dependency 的邊界,下一步才能分清楚一個經常混用的因果鏈:程式裡的 bug、系統內的錯誤狀態,和使用者真正看見的失敗,並不是同一件事。Day 10 會用 Fault → Error → Failure 把它們拆開。

延伸閱讀


上一篇
Day 08|Reliability、Quality、Safety:AI 系統不能只看一個指標
下一篇
Day 10(上)|Fault、Error、Failure:別把警報名稱當成根因
系列文
Learning SRE for the AI Era:從 SRE Lab 到 Production AI Reliability 共 44 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言