當上游源站發生故障 (超時、502、504、宕機) 時,ATS (Apache Traffic Server) 可透過兩種機制在快取中存在過期物件的情況下,暫時回傳舊內容給用戶,維持服務可用性,避免直接暴露錯誤碼。本文詳細說明兩種方案的配置、行為差異與回應標頭驗證方法。
原理: 在 ATS 回應處理階段 (TS_HTTP_READ_RESPONSE_HOOK) 檢查源站回應狀態碼,若為 502/504 且本地快取存在過期物件,則改寫回應為 200 OK 並輸出過期內容。
// 伪代碼邏輯
int handle_response(TSCont cont, TSEvent event, void *edata) {
TSMBuffer bufp; TSMLoc hdr_loc;
TSHttpTxnClientRespGet(cont, &bufp, &hdr_loc);
int status = TSHttpHdrStatusGet(bufp, hdr_loc);
if ((status == 502 || status == 504) && cache_has_stale_object()) {
TSHttpHdrStatusSet(bufp, hdr_loc, 200);
TSHttpHdrReasonSet(bufp, hdr_loc, "OK", 2);
// 移除錯誤相關標頭,插入快取內容
serve_stale_content(cont, bufp, hdr_loc);
}
TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
return TS_EVENT_CONTINUE;
}
優點: 精確控制觸發條件、可自訂降級邏輯 (如只針對特定路徑)。
缺點: 需 C 開發編譯 .so 外掛、部署維護成本高、升級 ATS 可能需重編譯。
proxy.config.http.cache.max_stale_age (推薦)原理: ATS 內建支援 RFC 5861 stale-while-revalidate / stale-if-error 語意。當源站不可達時,若快取物件過期時間未超過 max_stale_age,直接回傳過期內容 (狀態碼 200),並標記 Warning: 110 (過期) 或 111 (重新驗證失敗)。
CONFIG proxy.config.http.cache.max_stale_age INT 604800
# 單位:秒。預設 604800 (7 天)。過期後在此窗口內源站失效仍可服務舊內容。
# 相關建議配置
CONFIG proxy.config.http.cache.required_headers INT 1 # 必須有 Last-Modified 或 ETag
CONFIG proxy.config.http.cache.ignore_client_no_cache INT 1 # 忽略客戶端 no-cache
CONFIG proxy.config.http.cache.ignore_server_no_cache INT 1 # 忽略源站 no-cache (謹慎)
| 階段 | 源站狀態 | ATS 回應碼 | 關鍵回應標頭 | X-Cache / Via |
|---|---|---|---|---|
| 正常 | 200 OK | 200 | - | TCP_HIT / TCP_MISS |
| 源站首次失效 | Timeout / Down | 200 | Warning: 111 (Revalidation failed) | TCP_REFRESH_FAIL_HIT |
| 後續請求 (窗口內) | Down | 200 | Warning: 111 | TCP_HIT |
| 超過 max_stale_age | Down | 502 | - | TCP_REFRESH_FAIL_HIT / 502 |
curl -v -H "Host: example.com" https://ats-proxy:8080/resource
# 觀察:
# < Warning: 111 "Revalidation failed"
# < X-Cache: TCP_REFRESH_FAIL_HIT
# < Proxy-Connection: close (首次失效會關閉連線)
| 維度 | 方案一:外掛 | 方案二:內建配置 |
|---|---|---|
| 部署複雜度 | 高 (C 開發、編譯、部署) | 低 (修改 records.config 重載) |
| 靈活度 | 極高 (可針對 URL、Header、用戶分組) | 中 (全域或透過 cache.config 區分) |
| 維護成本 | 高 (ATS 升級需重編譯) | 低 (原生功能) |
| 效能影響 | 微小 (掛鉤點開銷) | 無額外開銷 |
| 推薦場景 | 複雜降級邏輯、多租戶差異化 | 大多數標準快取保護場景 |
max_stale_age 為 1~7 天 (視業務容忍度)。proxy.process.cache.stale_served 指標,警報異常飆升。cache.config 規則:url_regex=^/pay/ * max_stale_age=0。proxy.config.http.downstream_keep_alive 優化連線複用。