在用 ASP.NET MVC 3
重写博客园网站首页时,特地留意了一下这个缓存问题,通过这篇博文分享一下。
在 ASP.NET MVC 3
中如果使用了 OutputCache
,一定要在 Action
中添加下面的代码,切记!
Response.Cache.SetOmitVaryStar(true);
这是一个伴随ASP.NET从1.0到4.0的OutputCache
Bug,ASP.NET MVC 3
是基于 ASP.NET 4.0
的,所以也躲不过。
问题演示
下面先来体验一下不加 Response.Cache.SetOmitVaryStar(true);
的情况。
示例Action
代码:
[OutputCache(Duration = 120)]
public ActionResult SiteHome(int? pageIndex)
{
...
}
注:OutputCache.Location
的默认值是OutputCacheLocation.Any
(服务端、客户端、代理服务器端等都进行缓存)
第一次请求:
第二次请求(F5刷新浏览器):
第三次请求(F5刷新浏览器):
接着第四次请求会返回304
,第五次请求又返回200
。。。
再体验一下加 Response.Cache.SetOmitVaryStar(true);
的情况。
[OutputCache(Duration = 120)]
public ActionResult SiteHome(int? pageIndex)
{
Response.Cache.SetOmitVaryStar(true);
...
}
第一次请求:
第二次请求(F5刷新浏览器):
第三次请求(F5刷新浏览器):
注:只要在缓存有效期内,服务器一直返回304
。
问题分析
1. 200
与304
的区别
当返回状态码是200
时,服务器端会将当前请求的整个页面全部发送给客户端(消耗下行带宽)。
当返回状态码是304
时,由于客户端浏览器提供的 Last-Modified
时间在服务器端的缓存有效期内,服务器端只发送这个状态码,不发送页面的任何内容(几乎不消耗下行带宽),浏览器直接从本地缓存中获取内容。
所以,304
的好处就是节约带宽,响应速度更快。
2. 对服务端缓存的影响
加不加 Response.Cache.SetOmitVaryStar(true)
,服务端的缓存情况都是一样的。只是不加 SetOmitVaryStar(true)
时,对于同一个客户端浏览器,每隔一次请求,服务器端就不管客户端浏览器的缓存,重新发送页面内容,但是只要在缓存有效期内,内容还是从服务器端缓存中读取。
问题危害
ASP.NET
缓存的这个诡异行为,让你在不知不觉中浪费了带宽资源。
感想
用 ASP.NET 开发多年,这个伴随 ASP.NET
从 1.0 到 4.0 的 OutputCache
Bug 自己竟然在去年才发现。之前测试时第一次请求后按F5
看返回304
就以为没问题,而问题恰恰就在下一下F5
,偶尔多按一下F5
出现200
也没特别留意。由此可见,细心对程序员来说是多么重要,很多bug
、很多性能问题往往不是水平不够,而是不够细心。
优秀的程序员都是细心的人,不仅在写代码的时候细心,在生活中也同样细心。别看他木讷的样子,你对他所做的一切,他都会细心地观察到、体会到。做细心的程序员,珍惜细心的程序员!