在添加 cdn 後用戶端通路經常出現通路到曆史舊資料的情況,下面我們分析用戶端到伺服器端整條鍊路的情況分析出現曆史舊資料的原因以及規避方法。
現象分析

圖1. 浏覽器強緩存示意圖
而如果用戶端擷取的浏覽器驗證緩存也同樣是有可能擷取到曆史髒資料的。因為浏覽器端會和其通路資源的伺服器端進行 etag 或者 last-modified 字段驗證,如果其通路的伺服器為緩存伺服器(例如: cdn 等緩存伺服器)。而同樣緩存伺服器也是曆史髒資料的話就會導緻異常(如圖 2 所示)。
圖2. 浏覽器驗證緩存示意圖
規避方案
1. 用戶端清空浏覽器緩存
當懷疑浏覽器強緩存導緻的問題可以手動清空下浏覽器緩存或者通過 ctrl+f5 強制刷浏覽器緩存檢視是否恢複。
2. 禁止浏覽器緩存
上述方法僅能夠臨時解決,如果該資源不想其因為浏覽器緩存導緻髒資料的話可以設定該資源的 response 頭中的 cache-control 或者 expires 為 no-cache, no-store, private即可禁止浏覽器緩存。
注意:上述的 response 頭中的 cache-control 或者 expires 設定也同樣會影響 cdn 的緩存。如果希望 cdn 加速的資源可以在 cdn 上緩存但是禁止在浏覽器緩存的話可以在 cdn 上設定 http 頭,該 http 頭不影響 cdn 緩存政策,僅影響用戶端浏覽器緩存政策(配置如圖 3 所示)。
圖3. cdn 設定 http 頭示意圖
終端裝置正常請求應該是到緩存伺服器 cdn 或者伺服器上,但是有時會出現該資源請求被 301 或者 302 跳轉到某台伺服器傳回資料,例如圖 4 所示,該 ip 并非是伺服器的 ip ,被跳轉到營運商的緩存伺服器。 這種現象一般出現在局部地區的個别終端裝置中,并非在全局範圍内影響。
圖4. 通路出現劫持示意圖
1. 回報當地營運商跟進該問題
因為該問題主要在用戶端到伺服器端的營運商鍊路出現的問題,通過伺服器端不好解決該問題,建議可将該問題回報給營運商解決該問題。
cdn 作為内容分發網絡,是會将使用者源站的資源緩存到各個 cdn 節點。 cdn 當源站做同名更新時是不會主動回源拉取新資源的( oss 除外,詳細見規避方案 4 )。除非當用戶端發起請求後,對應 cdn 節點上該資源沒有緩存或者緩存已經過期才會回源拉取最新的資料。
使用者可以通過擷取資源的 response 頭中檢視到該資源的緩存情況。如圖 5
中所示, via 投中分别辨別了 cdn 的 l2 節點和 l1 節點,如果兩者之中有一個是 "h" 的狀态即表示 cdn 是命中狀态,此時是不會回源拉取最新資料的。圖 5 中即是 cdn l2 節點命中的狀态。
圖5. cdn 的response 頭示意圖
1. 手動重新整理 cdn 緩存,重新觸發回源請求
注意: cdn 的目錄重新整理是會重新整理該目錄下的所有子目錄和檔案的,是以目錄重新整理是有可能引起大量回源請求的。
2. 源站盡量避免同名更新,可以給檔案增加版本号差別
建議使用者靜态資源做版本更新的時候可以通過版本号進行差別,例如在 url 中帶上 “?version=1.0” 進行區分,這樣避免應用系統疊代後仍然擷取之前版本資料。
3. 資源經常同名更新則應該設定其不在 cdn 緩存
4. 當 cdn 的源站為 oss 時可以設定自動重新整理功能
當 cdn 的源站是 oss 的話是可以設定自動重新整理功能的,請您參考圖 6 。當 cdn 的加速域名也同樣在 oss 的自定義域名進行綁定後即可開啟該自動重新整理功能。然後當 oss 中的檔案出現同名更新的話就會自動下發 cdn 重新整理任務以保證 cdn 上該資源的緩存不可用。
圖6. oss 配置 cdn 緩存自動重新整理示意圖
常見的使用者架構中是 cdn 回源到反向代理伺服器,然後通過反向代理到真正的源站伺服器。在這種場景下如果反向代理伺服器開啟了緩存功能也同樣會在源站伺服器進行更新後仍然出現曆史髒資料。測試通過代理伺服器和源站伺服器傳回資料不一緻即可确認為該問題。
1. 關閉代理伺服器的緩存功能
反向代理伺服器的緩存功能使用者是可以選擇是否開啟緩存功能。例如使用 nginx 伺服器作為反向代理伺服器時是通過 proxy_cache 子產品設定緩存的。使用者可以關閉該子產品功能即可取消緩存的功能,其他的 web 伺服器配置具體見對應伺服器的官方配置文檔。
2. 清空代理伺服器緩存
使用者在更新過源站伺服器後可以清除代理伺服器的緩存内容,不同的代理伺服器有不同的清除方法,在 nginx 伺服器中是沒有直接提供清除指定 url 緩存的功能的,常見的方法是使用 ngx_cache_purge 第三方子產品進行清理。