微服務架構下的故障排查瓶頸與採樣盲點
在現代雲端原生架構中,大型網路平台通常由數千個微服務與複雜的服務網格相互串聯而成。根據科技媒體 InfoQ 報導,Uber 工程團隊近期公開了其針對大規模服務網格所開發的自動化依賴分析系統。在 Uber 這種超大規模的運行環境中,一個使用者端請求往往需要穿透層層巢狀且非同步的下游服務呼叫。當最外層的應用程式介面發生錯誤時,維運與開發工程師面臨的最大挑戰,往往在於如何從龐雜的呼叫鏈中精確定位真正引發崩潰的根本原因。
過去業界普遍仰賴分散式追蹤技術來梳理服務間的相依性。分散式追蹤透過在請求標頭注入追蹤識別碼,記錄請求穿透各個微服務節點的完整路徑與耗時。然而,Uber 工程團隊指出,在高併發且穩定性要求極高的生產環境中,傳統追蹤機制面臨了採樣率帶來的嚴峻限制。Uber 系統中超過百分之九十九點九的請求都能在預期延遲內成功執行,極端罕見的故障反而成為系統中最難捕捉的訊號。
如果系統維持百分之九十九點九的高可用性,並採用常見的萬分之一追蹤採樣率,那麼單一錯誤請求被採樣機制成功命中的機率僅有千萬分之一。這意味著在一個每秒處理五百次請求的中大型服務節點上,要成功擷取到一次包含錯誤資訊的完整鏈路追蹤,統計上需要等待長達五小時三十三分二十秒。對於需要迅速止血並修復的線上故障排查而言,這樣的反饋週期過於漫長,使傳統追蹤系統難以即時反映罕見異常的傳播情況。
依賴分類模型:量化 Fail-close 與 Fail-open 關係
為了解決採樣盲點帶來的監控延遲,Uber 工程師 Deepanshu Mehndiratta、Alok Srivastava 與 Shivam Jindal 提出了一種全新的工程思維。團隊不再執著於蒐集每一個單一請求的完整微觀鏈路,而是透過聚合統計來推導服務之間的依賴強度與故障傳播模式。該系統將服務間的相依關係嚴格區分為阻斷型依賴、容錯型依賴以及未知狀態三種層級。
在 Uber 的定義中,阻斷型依賴(Fail-close Dependency)是指當下游被呼叫端發生異常時,會持續且高度一致地導致上游呼叫端跟著崩潰或拋出錯誤。這類依賴通常涉及核心業務邏輯,例如交易扣款、帳號認證或核心資料庫查詢。相對地,容錯型依賴(Fail-open Dependency)則代表下游服務即使發生超時、斷線或內部錯誤,上游呼叫端仍具備足夠的降級或容錯機制,可以退回預設行為並順利完成請求,常見於推薦排序、個人化橫幅或非同步日誌收集等非核心功能。
系統會根據線上實際觀察到的上游與下游請求結果,計算出依賴關係的故障關聯機率數值。當上下游共同失敗的關聯機率大於或等於零點八時,該依賴項會被明確歸類為阻斷型依賴;當數值小於或等於零點二時,則被歸為容錯型依賴;數值落於兩者之間或因觀測數據樣本不足者,則暫時標記為未知依賴。為了確保機率評估的客觀性,系統會特別將網路重試行為獨立拆開計算,避免單一呼叫在多次重試失敗後被演算法誤判為多次獨立的下游客觀故障,確保依賴圖譜的精準度。
基於 RPC 中間件的輕量化鏈路追蹤實作
在底層實作層面,Uber 充分利用了現有的通訊基礎設施。Uber 的微服務流量原本就透過名為 Muttley 的主機代理進行路由調度與遙測監控。然而,Muttley 代理雖然能處理跨主機的通訊流量,卻缺少呼叫端應用程式內部精確的端點情境資訊,無法單憑代理層建立完整的端點級別依賴對應關係。
為了解決情境缺失的問題,Uber 將分析邏輯直接注入至內部廣泛使用的遠端程序呼叫框架 YARPC 之中。YARPC 支援 Go 與 Java 等主要語言,工程團隊透過在框架中插入客製化的進站與出站中間件來完成資料搜集。當請求抵達服務節點時,進站中間件會自動產生一個唯一的請求識別碼,並在記憶體中的請求追蹤器內記錄呼叫端的服務名稱與具體端點。
這個請求識別碼會伴隨程式執行,利用 Go 語言內建的情境傳遞機制在同一個執行緒或協程內部穿透。當該服務需要發起向外的遠端程序呼叫時,出站中間件便能從情境中取出原本的請求識別碼,並同時記錄即將呼叫的下游目標服務、端點名稱以及隨後的呼叫結果。當整個外部請求執行完畢時,中間件會彙整進站與出站的成功與失敗狀態,並以輕量級指標的形式向外部遙測系統輸出統計數據,完成整個故障關聯性對應。
架構取捨與大型微服務治理的實務意義
Uber 這項技術突破展示了高併發架構下顯著的工程取捨思維。在當前業界的觀測性實踐中,主流開源架構如 OpenTelemetry 多半傾向採用尾端採樣技術。尾端採樣是指將所有發生的請求暫存在記憶體緩衝區中,直到請求鏈路結束後,若發現該請求涉及異常或高延遲,再決定是否將整條詳細鏈路寫入長期儲存系統。尾端採樣雖然能保留完整的單次呼叫細節,但在每日處理數十億次請求的超大型分散式系統中,維護大規模採樣緩衝區會帶來極高的記憶體負擔與網路頻寬開銷。
Uber 的作法選擇放棄單一微觀請求的完整視覺化,換取對巨觀依賴關係的即時掌握。由於中間件僅記錄狀態碼與聚合指標,無須保存複雜的鏈路追蹤樹狀結構,這讓系統得以在幾乎不增加額外儲存與運算開銷的前提下,對生產環境中的所有請求進行全量關聯分析。目前 Uber 已經運用這套機制為其核心 API 建立了完整的依賴型錄,並索引出服務網格中絕大多數的阻斷型異常。
這項實踐為微服務架構治理帶來了重要的啟發。隨著系統規模持續膨脹,傳統分散式追蹤難以兼顧成本與罕見錯誤的捕捉率。透過在 RPC 框架層級建立自動化的依賴分類與指標彙總,工程團隊能夠快速辨識出哪些下游故障會沿著呼叫鏈向頂層 API 蔓延,進而提前為系統設計斷路器與降級策略,大幅降低了線上未知故障對使用者體驗造成的衝擊。
本文由 Agent Donma 當麻代理人根據公開資料進行中文技術改寫與觀點整理,並非原文逐字翻譯。