5.7 錯誤處理與測試在高併發服務中的角色
5.7 錯誤處理與測試在高併發服務中的角色
高併發服務的可靠性來自錯誤處理與測試共同形成的保護機制。錯誤處理讓失敗路徑可見,測試讓失敗路徑可重現;兩者一起決定系統在壓力下是否仍能被理解、修復與持續交付。
本章目標
學完本章後,你將能夠:
- 把錯誤處理看成可靠性的一部分
- 區分可恢復錯誤與不可恢復錯誤
- 用測試保護失敗路徑與並發路徑
- 讓 timeout、取消與 race condition 能被提早發現
- 理解為什麼高併發服務更需要明確的測試邊界
【觀察】錯誤是服務常態
在高併發服務裡,錯誤是日常情況的一部分。網路會失敗、下游會超時、資料會不完整、狀態會競爭;這些情境都應進入系統設計,而不是只留給事故發生後人工排查。
Go 把錯誤放在回傳值中,就是要讓這些常態能被直接看見。
【判讀】測試要先保護脆弱邊界
高併發服務最容易出問題的地方,通常是:
- HTTP handler 與外部輸入邊界
- goroutine 之間的共享狀態
- timeout 與 cancellation
- event / queue 的重複或漏處理
這些邊界都應該有測試。人工驗證可以輔助檢查流程,但它無法穩定重現 timeout、取消、race condition 與高併發失敗路徑。
【策略】錯誤路徑也要被測
服務測試需要同時覆蓋成功路徑與失敗路徑。只驗證成功路徑會讓 timeout、下游錯誤、取消與狀態競爭在壓力下才暴露,修復成本會更高。
你至少應該測:
- 參數不合法時是否回傳穩定錯誤
- 下游失敗時是否有正確的包裝錯誤
- timeout 是否真的會停止工作
- 取消 context 後 goroutine 是否退出
【執行】並發測試要看資源是否被正確回收
高併發測試的核心目標是確認資源會被正確回收。跑很多 goroutine 只是製造壓力;真正需要驗證的是:
- goroutine 會不會 leak
- channel 會不會卡住
- 鎖的範圍是否合理
- 資源關閉後流程是否停止
可靠性測試至少要證明流程能正確結束。只證明「看起來可以跑」會漏掉 goroutine leak、channel 卡住、鎖範圍過大與資源未釋放等問題。