工程 · 1 min read
Proxy 不接受 HEAD,刷新永遠失敗
LB cache 用 HEAD refresh 大檔案,但用 Gin 寫的 Go proxy 只註冊 GET,於是回 405。一個框架預設不支援的 method,就讓整層 cache 失效。
LB cache 用 HEAD refresh 大檔案。我們的 proxy 只接受 GET,所以回 405,副本就一直是過期的。
上一篇的問題是:背景 refresh 為什麼一直失敗(Stale-while-revalidate:先回舊檔,背景再刷新)?我打開 proxy 的 log 和程式碼。
// router
engine.GET("/*path", RootHandler) // 只註冊 GET
// server
engine.HandleMethodNotAllowed = true // 路徑對、method 錯 → 405
- Proxy 用 Go 的 Gin 框架。它對所有路徑只註冊 GET,沒有任何路由接受 HEAD。
HandleMethodNotAllowed = true讓 Gin 回 405,而不是 404。- 雲端 storage、nginx 和 Go 標準函式庫
net/http預設都會用 GET 的路由回答 HEAD。Gin 不會。
我在 log 裡看到的
| 觀察 | 結果 |
|---|---|
| 進 proxy 的 HTML request | 每秒十幾個 |
| 其中是 HEAD、拿到 405 的 | 75% |
| 405 的 user agent | LB cache 自己 |
| 拿到 405 最多的檔案 | 3.5 到 4.3 MB 的 HTML |
| 拿到 304 最多的檔案 | 都小於 1 KB |
我透過 CDN 打了 7 個 request,proxy log 在同一秒出現 7 行 HEAD 405。最糟的檔案是 3.65 MB,每 0.24 秒就被 fetch 一次。
LB cache 對大檔案改用 HEAD refresh,是我從 log 推出來的。官方文件沒有寫。
一個框架預設不支援的 method,就能讓整層 cache 失效。
延伸閱讀:一個 HTTP request、Stale-while-revalidate:先回舊檔,背景再刷新、五個零件串成一個迴圈。或回到系列總覽。