工程 · 2 min read
Stale-while-revalidate:先回舊檔,背景再刷新
Stale-while-revalidate 先回舊副本,再在背景 refresh。只要 refresh 一直失敗,副本就永遠新鮮不起來,還帶著很大的 Age 往前傳。
副本過期時,LB cache 先把舊副本回出去,再在背景 refresh。Refresh 一直失敗,副本就永遠新鮮不起來。
Proxy 路線的 LB cache 不讀 bypass header(Bypass header 只在有規則的地方有效)。但它的副本早就過期了,為什麼還一直回給 Akamai?
- 這個行為在 HTTP 標準裡叫 stale-while-revalidate(RFC 5861)。我們的 LB cache 用自己的設定開啟它。
- 這個設定是過期後還能回舊副本的秒數。我們 proxy 後端的值是 86400 秒(1 天)。
- 沒有人刻意選這個值,它是預設值(三個地方都在設定 TTL)。
- 好處:回應很快。origin 掛掉時,使用者還是拿得到檔案。
- 代價:如果背景 refresh 每次都失敗,副本就一直是過期的。
舊副本帶著很大的 Age 往前傳
- LB cache 把舊副本交給 Akamai 時,
Age已經超過 3600。 - Akamai 算出的剩餘新鮮時間是 0 或負數。
- 所以 Akamai 只能保留它 1 秒(
max-age=1),下一個 request 又要去問。 - 這就是 Cache 的新鮮度:fresh、stale 和 304 說的:前面的 cache 只會跟它收到的副本一樣新。
這個後端在 IaC 裡沒有任何 cache 設定。但 cache 開著,所以有一整套預設值。讓 bug 發生的 86400,就藏在沒人寫下來的預設值裡。
「先回舊檔」是一種保護。前提是背景的 refresh 真的會成功。
參考來源:RFC 5861: HTTP Cache-Control Extensions for Stale Content
延伸閱讀:Cache 的新鮮度:fresh、stale 和 304、三個地方都在設定 TTL、Bypass header 只在有規則的地方有效、Proxy 不接受 HEAD,刷新永遠失敗。或回到系列總覽。