Skip to content
BEE
Backend Engineering Essentials

[BEE-15006] 生產環境中的測試

INFO

金絲雀分析、合成監控與可觀測性驅動的測試。

背景

預生產環境無法複製最關鍵的要素:真實的流量模式、真實的資料分佈以及真實的規模。測試環境可能通過所有測試套件,但生產部署卻在流量峰值、異常查詢模式,或從未出現在測試資料中的邊緣案例下悄悄降級。

Honeycomb 技術長 Charity Majors 對此有清楚的論述:開發者的工作不是在程式碼提交時完成的,而是在你能夠驗證程式碼在生產環境中正確運作時才算完成。可觀測性驅動開發意味著在撰寫程式碼時就進行儀器化,部署到生產環境,然後透過這些儀器化工具審視系統行為。問題不在於是否要在生產環境中測試,而在於如何安全地進行。

在生產環境中測試並不是取代預生產測試的手段。單元測試、整合測試和契約測試仍然屬於 CI 流程。預生產測試在受控條件下驗證正確性;生產測試在真實條件下驗證行為。兩者都是必要的。

原則

依據每項變更的風險,使用分層的生產測試技術,並在每一層控制爆炸半徑。

從最低風險到最高風險的光譜:

以下依照爆炸半徑從低到高描述各項技術。

合成監控

合成監控以排程方式對線上生產系統執行自動化探針,模擬特定的使用者旅程。與真實使用者監控(RUM)不同,合成探針完全可控:你清楚知道發送了什麼請求、預期的回應是什麼,以及檢查何時執行。

合成監控的用途:

  • 持續斷言關鍵路徑(登入、結帳、搜尋、API 健康端點)維持正常運作。
  • 在真實使用者遇到問題之前,立即偵測部署後的退步。
  • 建立 SLA 基準:如果合成探針看到 p99 延遲超過閾值,在使用者發現之前就發出告警。

未涵蓋關鍵路徑的合成探針只會提供虛假的信心。先繪製最重要的使用者旅程,確保每一條旅程都有對應的合成檢查。

影子流量(暗發布)

影子流量,又稱暗發布,會複製生產請求並同時發送給新版本服務。新版本處理請求,但其回應會被丟棄——使用者持續收到現有版本的回應。

此技術允許你:

  • 在不讓任何使用者暴露的情況下,驗證新版本是否能處理真實的查詢量和流量型態。
  • 比較新舊版本的輸出,發現行為差異(偏差測試)。
  • 在任何使用者接觸到問題之前,識別延遲退步和基礎設施容量問題。

關鍵陷阱: 影子流量不能有副作用。如果新服務寫入資料庫、發送電子郵件、收取款項或產生 Kafka 事件,這些副作用會影響真實資料,即使回應被丟棄。在執行影子流量之前,審計所有寫入路徑,將其存根化或導向獨立的測試命名空間。

GoReplayDiffy(曾在 Twitter、Airbnb 使用)等工具可以自動化影子流量擷取與偏差分析。

金絲雀部署

金絲雀部署將小比例的線上流量——通常是 1–10%——路由到新版本,其餘流量繼續使用穩定版本。兩個版本同時運行,可觀測性工具比較其指標以偵測退步。

金絲雀分析聚焦於:

  • 錯誤率:金絲雀的 5xx 錯誤率是否高於基準線?
  • 延遲:金絲雀的 p95 或 p99 延遲是否增加?
  • 業務指標:轉換率、成功率或特定領域的 KPI 是否降低?
  • 資源消耗:CPU 或記憶體使用量是否異常增加?

通用的系統儀表板對金絲雀分析來說是不夠的。對於每次部署,定義對該變更最敏感的具體指標。部署新的付款處理器?監控付款成功率和交易拒絕率。通用的 CPU 圖表無法發現付款路由中的細微邏輯錯誤。

自動化金絲雀的晉升和回滾。如果金絲雀指標在定義的時間段內保持在可接受的範圍內,則晉升至 100%。如果任何指標超過閾值,則自動回滾。

另見:BEE-16002 — 金絲雀部署,了解實作細節。

功能旗標逐步發布

功能旗標將部署與發布解耦。程式碼以停用狀態發布到生產環境,然後逐步為特定使用者群體啟用:內部使用者、Beta 群體、1%、10%、50%、100%。

這帶來的好處:

  • 即時回滾,無需重新部署:發現問題時停用旗標即可。
  • 精準曝光:先為內部使用者或特定地區啟用,驗證後再擴展。
  • 逐步增加風險:將每個增量視為新的金絲雀。在每次增量後監控,再決定是否繼續。

功能旗標與金絲雀部署結合時最為強大:金絲雀控制基礎設施層級的曝光,功能旗標則獨立控制應用程式層級的曝光。

另見:BEE-16004 — 功能旗標

可觀測性作為測試裁判

在預生產測試中,斷言是明確的:assertEqual(result, expected)。在生產測試中,裁判是你的遙測資料。結構化日誌、分散式追蹤和指標是你用來斷言生產行為符合意圖的機制。

這意味著:

  • 在發布前進行儀器化:為新程式碼引入的特定行為添加結構化日誌欄位和追蹤 span。如果你無法觀測到它,就無法測試它。
  • 提前定義成功標準:在執行金絲雀之前,寫下「通過」的標準——具體的指標閾值、具體的錯誤率上限。這能防止對不良結果進行事後合理化。
  • 使用 SLO 作為閘道:降低 SLO 錯誤預算的金絲雀應自動判定失敗。見 BEE-14005 — 以 SLO 作為成功標準

A/B 測試作為生產測試

A/B 測試是一種生產測試形式,針對使用者面向的結果指標衡量兩個變體。與金絲雀不同——金絲雀是測試退步——A/B 測試衡量的是變更是否改善了目標指標。

紀律是相同的:在執行實驗之前定義成功標準,對結果指標進行儀器化,以統計效力考量分配流量,並且不要為了釣到顯著性而將實驗延伸超過決策點。

工作範例:部署新的搜尋演算法

假設你正在替換產品目錄搜尋的文字搜尋演算法。

第一步——影子流量(零使用者曝光)

擷取生產搜尋查詢,並同時在現有服務旁邊向新搜尋服務重播。記錄兩組結果集。使用偏差工具識別排名結果有顯著差異的查詢。驗證新演算法在可接受的 CPU 和記憶體範圍內處理查詢量。沒有任何使用者看到新的結果。

第二步——金絲雀部署(5% 流量)

將 5% 的線上搜尋流量路由到新演算法。提前定義成功指標:

  • p95 搜尋延遲增加不超過 20ms。
  • 搜尋錯誤率保持在 0.1% 以下。
  • 搜尋結果的點擊率(CTR)相對下降不超過 2%。

如果所有指標在 48 小時內保持正常,金絲雀健康。

第三步——功能旗標逐步發布(5% → 100%,歷時一週)

以增量方式提高旗標百分比:5% → 20% → 50% → 100%,每個步驟設有 24 小時的觀察窗口。在每個增量後監控相同的指標。如果 CTR 在 50% 時降低,回滾到 20% 並在繼續之前進行調查。

常見錯誤

1. 沒有爆炸半徑控制 在生產環境中測試而不限制影響範圍,意味著一個錯誤同時影響所有使用者。上述每種技術的存在都是為了限制範圍。如果你沒有明確控制爆炸半徑,你不是在生產環境中測試——你只是在部署到生產環境並寄望不出問題。

2. 沒有回滾計畫 在執行任何生產測試之前,定義回滾程序並驗證其有效性。沒有自動化或充分演練回滾的金絲雀,只是一次緩慢的全量部署。

3. 影子流量有狀態變更的副作用 寫入生產資料庫、觸發電子郵件或遞增計費計數器的影子請求,即使回應被丟棄,也會污染真實資料。在執行影子流量之前,審計所有寫入路徑。這是最常見也最危險的影子流量錯誤。

4. 合成監控遺漏關鍵路徑 只檢查 /health 而不檢查結帳流程的合成套件提供的是虛假的信心。先繪製使用者旅程,再撰寫探針。每當新增使用者關鍵路徑時,審查覆蓋範圍。

5. 以生產測試為藉口跳過預生產測試 生產測試可以發現預生產無法模擬的真實世界行為。它無法發現一個良好結構的測試套件能在幾秒內發現的邏輯錯誤、型別錯誤或契約違規。兩個層次都是必要的。

相關 BEE

參考資料

  • Charity Majors,「Go Ahead, Test in Production」— The New Stack
  • Majors、Fong-Jones、Miranda — Observability Engineering: Achieving Production ExcellenceO'Reilly
  • Google SRE Workbook — "Canarying Releases" — sre.google
  • Microsoft Engineering Fundamentals — "Shadow Testing" — github.io
  • Datadog — "Best Practices for Monitoring Dark Launches" — datadoghq.com
  • Martin Fowler — "Canary Release" — martinfowler.com