首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

ASP.NET OutputCache Vary:* Bug 深度解析:從 1.0 到 4.0 的十年陷阱

     編輯:ASP.NET 基礎

Bug 現場重現


<%@ OutputCache Duration="300" VaryByParam="*" %>

Firefox + Firebug 觀察響應頭:

  1. 首次請求:`200 OK`,`Cache-Control: public, max-age=300`,`Vary: Accept-Encoding`(IIS 動態壓縮)
  2. F5 刷新:`304 Not Modified` ✅ 瀏覽器緩存生效
  3. 再次 F5:`200 OK` ❌ **緩存失效**,響應頭出現 **`Vary: *`**

Vary:* 的災難性後果

HTTP 規範:`Vary: *` 意味著「響應隨**任意**請求頭變化」,瀏覽器**必須視為不可緩存**,每次都重新請求服務器。

  • 瀏覽器緩存完全失效
  • CDN/代理緩存失效
  • 服務器負載、頻寬雙雙浪費

Bug 歷史脈絡

根因代碼分析

ASP.NET 內部邏輯:

  1. `VaryByParam="*"` 設置內部標記 `varyByAllParams = true`
  2. 生成響應頭時,若 `varyByAllParams` 為真,**無條件寫入 `Vary: *`**
  3. 完全忽略 `SetOmitVaryStar` 設置(除非手動調用)

一行代碼修復


protected void Page_Load(object sender, EventArgs e)
{
    Response.Cache.SetOmitVaryStar(true); // 關鍵:抑制 Vary: *
}

加上這行後,刷新測試:

  • 響應頭不再包含 `Vary: *`
  • 瀏覽器緩存持續命中 `304 Not Modified`
  • CDN/代理緩存正常工作

最佳實踐建議

  1. 基頁面統一修復:在 `BasePage.OnLoad` 或 `Global.asax Application_PostAcquireRequestState` 中統一調用 `Response.Cache.SetOmitVaryStar(true)`
  2. 精確指定 VaryByParam:避免使用 `"*"`,改為實際參數如 `"id;category;page"`,從源頭避免 `varyByAllParams`
  3. MVC 專案無此問題:`OutputCacheAttribute` 實現邏輯不同,不產生 `Vary: *`
  4. 關閉 IIS 動態壓縮測試**:若關閉動態壓縮,`Vary: Accept-Encoding` 消失,但 `Vary: *` 依然存在,證明兩者無關

驗證清單


✅ 響應頭無 Vary: *
✅ 瀏覽器 F5 持續 304
✅ Cache-Control: public, max-age=XXX 存在
✅ CDN 緩存命中率提升

微軟官方文檔引用

ASP.NET 4 Breaking Changes - "Output Caching Changes to Vary * HTTP Header"
"In ASP.NET 4, the decision was made to fix the root problem. The Vary:* HTTP header is no longer emitted from responses that specify Location='ServerAndClient'."

實測結論:文檔所述修復**僅針對 `Location="ServerAndClient"`**,默認 `Location="Any"` **仍存在 Bug**,需手動調用 `SetOmitVaryStar(true)`。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
版本表現微軟對策
ASP.NET 1.0`Location="ServerAndClient"` 產生 `Vary: *`—
ASP.NET 1.1同上新增 `HttpCachePolicy.SetOmitVaryStar(true)` 抑制
ASP.NET 4.0**文檔宣稱修復****實測未修復**:`Location="Any"` (默認) 仍產生 `Vary: *`