问题 HTTP缓存混乱


我不确定这是否是服务器问题,或者我是否无法理解HTTP缓存是如何工作的。

我有一个在IIS7上运行的ASP MVC应用程序。作为网站的一部分,有很多静态内容,包括大量的CSS,Javascript和图像文件。

对于这些文件,我希望浏览器将它们缓存至少一天 - 我们的.css,.js,.gif和.png文件很少更改。

我的web.config是这样的:

<system.webServer>
    <staticContent>
        <clientCache cacheControlMode="UseMaxAge" 
                     cacheControlMaxAge="1.00:00:00" />
    </staticContent>
</system.webServer>

我得到的问题是浏览器(经过测试的Chrome,IE8和FX)似乎没有像我期望的那样缓存文件。我有默认设置(在IE中自动检查新页面)。

首次访问内容时按预期下载

HTTP/1.1 200 OK
Cache-Control: max-age=86400
Content-Type: image/gif
Last-Modified: Fri, 07 Aug 2009 09:55:15 GMT
Accept-Ranges: bytes
ETag: "3efeb2294517ca1:0"
Server: Microsoft-IIS/7.0
X-Powered-By: ASP.NET
Date: Mon, 07 Jun 2010 14:29:16 GMT
Content-Length: 918

<content>

我认为 Cache-Control: max-age=86400 应告诉浏览器一天不再请求该页面。

好的,现在重新加载页面,浏览器再次请求图像。这次它使用这些标头获得空响应:

HTTP/1.1 304 Not Modified
Cache-Control: max-age=86400
Last-Modified: Fri, 07 Aug 2009 09:55:15 GMT
Accept-Ranges: bytes
ETag: "3efeb2294517ca1:0"
Server: Microsoft-IIS/7.0
X-Powered-By: ASP.NET
Date: Mon, 07 Jun 2010 14:30:32 GMT

所以看起来浏览器发送了 ETag 返回(作为资源的唯一ID),服务器返回一个 304未修改  - 告诉浏览器它可以使用以前下载的文件。

在我看来,这对许多缓存情况都是正确的,但在这里我不想要额外的往返。当服务器上的文件发生变化时,我不关心图像是否过时。

有很多这些文件(即使使用精灵地图等),我们的许多客户都有非常慢的网络。为此每次往返 304 状态大约需要10到5秒。许多人还拥有IE6,它一次只有2个HTTP连接。最终结果是我们的应用程序对于这些客户端来说似乎非常慢,每个页面花费额外的几秒钟来检查静态内容是否未发生变化。

我错过了什么响应标题会导致浏览器积极地缓存文件?

我如何在IIS7的.Net web.config中设置它?

我是否误解了HTTP缓存的工作原理?


7435
2018-06-07 14:42


起源

你能禁用ETag吗?这可能会解决你,但我不确定。 - NG.
我将尝试删除ETag,但对于我的测试服务器,它似乎匹配 - Keith
如果您点击刷新或F5,浏览器将始终发出服务器请求(可能是条件请求),而不管缓存设置如何 - Sripathi Krishnan
@sri谢谢!就是这样!事实证明 Expires 和 Cache-Control 同样工作,但F5 /刷新总是导致304检查再次发生。但在答案中你可以有一些代表:) - Keith


答案:


您需要使用Expires指令,否则浏览器将始终检查内容是否已更新。

如果缓存条目具有有效的到期日期,则浏览器可以重用该内容,而无需在重新访问页面或站点时完全联系服务器。这大大减少了频繁访问的页面的网络往返次数。例如,Google徽标设置为在2038年到期,只会在您第一次访问google.com时下载,或者如果您清空了浏览器缓存。如果他们想要更改图像,他们可以使用不同的图像文件名或路径。

要在IIS7中更改使用以下内容。如果将静态内容保存在特定目录中,则最容易管理。

登录服务器
打开IIS管理器(开始 - >管理工具 - > iis manager
展开服务器节点
展开站点节点
打开站点并导航到要更改的目录
打开IIS HTTP响应标头部分
单击右侧任务窗格上的“设置公共标题”
根据您的应用需要设置“过期网页内容”。


6
2018-06-07 14:48



谢谢 - 你在IIS7中的步骤实际上会生成相同的web.config XML,但在我的问题中。 - Keith


使用expires标头而不是使用cache-control。第一次从我的浏览器缓存向我提供内容,直到此到期日为止。在您的到期日之前,不会对文件中的更改进行交叉检查。

在web.config的system.webServer部分添加标题,如下所示:

<system.webServer>
    <staticContent>
        <clientCache httpExpires="Sun, 29 Mar 2020 00:00:00 GMT" 
                     cacheControlMode="UseExpires" />;
    </staticContent>
</system.webServer>

5
2018-06-07 14:45



我将如何在IIS7中执行此操作?另外 - 为什么这样做呢 cache-control 不? - Keith
谢谢你的澄清 - 所以 cache-control 破碎? - Keith
不,我相信你和我都缺少的东西我正在阅读有关缓存控制的更多内容,如果我弄清楚的话会让你知道。是的,但我的建议对你有用 - sushil bharwani
您的XML配置在此设置静态内容以使用HTTP Expires 标题,而我的问题导致它使用 Cache-Control 头。经过一些调查后,似乎工作正常,但有些旧的浏览器无法识别 Cache-Control (在IE 5.5之前)。网上有很多建议可以使用 Expires,但我们不支持IE5,所以这不是问题。谢谢你的答案(+1) - Keith


Short anwser:删除Etag并使用Expire标头。

你应该看看 35 Yahoo性能最佳实践,更具体地说:

对于每个规则,它们通常涵盖Apache和IIS Web服务器配置。

编辑:好吧,看起来没有简单的方法来删除IIS中的Etags, 除了安装一些第三方软件...


-1
2018-06-07 14:58



不幸的是,似乎无法删除IIS7上的ETag - 请参阅 stackoverflow.com/questions/477913 - Keith
为什么会这样 expire 标头工作时 cache-control 不?我们不必支持IE5和过去支持HTTP 1.1的所有内容 - Keith
谢谢你的答案(+1)。 Expires 和 Cache-Control 同样工作得很好(除非你是IE5或更低版本,否则只有 Expires 只要两者都设置好你。事实证明我的实际问题是我正在按F5 /刷新来检查,这总是导致浏览器ping每个文件并获得 304未修改响应。 - Keith