【问题标题】:HTTP caching confusionHTTP缓存混乱
【发布时间】:2010-06-07 14:42:02
【问题描述】:

我不确定这是否是服务器问题,或者我是否无法理解 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 Not Modified - 告诉浏览器它可以使用之前下载的文件。

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

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

我缺少什么会导致浏览器主动缓存文件的响应标头?

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

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

【问题讨论】:

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

标签: http iis iis-7 caching


【解决方案1】:

你需要使用Expires指令,否则浏览器会一直检查内容是否更新。

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

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

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

【讨论】:

  • 谢谢 - 你在 IIS7 中的步骤实际上会产生与我的问题相同的 web.config XML。
【解决方案2】:

使用过期标头而不是使用缓存控制。请告诉您的服务器第一次从我的浏览器缓存中为我提供内容,直到此过期日期。在您的到期日期之前,不会对文件更改进行交叉检查。

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

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

【讨论】:

  • 如何在 IIS7 中做到这一点?另外 - 为什么 cache-control 不起作用时它会起作用?
  • 感谢您的澄清 - cache-control 坏了吗?
  • 不,我相信你和我都缺少一些东西,我正在阅读更多关于缓存控制的内容,如果我弄清楚了,我会告诉你。是的,但我的建议对你有用吗
  • 您的 XML 配置在此处将静态内容设置为使用 HTTP Expires 标头,而我的问题导致它使用 Cache-Control 标头。经过一番调查,似乎两者都可以正常工作,尽管一些非常旧的浏览器无法识别Cache-Control(在 IE 5.5 之前)。网上有很多建议使用Expires,但我们不支持IE5,所以这不是问题。感谢您的回答(+1)
【解决方案3】:

简短的回答:删除 Etag 并使用 Expire 标头。

您应该查看35 Yahoo Performance best practices,更具体地说:

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

编辑:好的,看来没有简单的方法可以在 IIS 中删除 Etag,besides installing some 3rd party software...

【讨论】:

  • 不幸的是,似乎无法删除 IIS7 上的 ETag - 请参阅 stackoverflow.com/questions/477913
  • 为什么expire 标头会起作用,而cache-control 不起作用?我们不必支持 IE5 以及过去支持 HTTP 1.1 的所有内容
  • 感谢您的回答 (+1)。 ExpiresCache-Control 工作得一样好(除非你在 IE5 或更低版本上,那么只有 Expires 可以)只要你设置好了。事实证明,我的实际问题是我按 F5/refresh 进行检查,这总是导致浏览器对每个文件执行 ping 操作并获得 304 Not Modified 响应。
猜你喜欢
  • 2023-03-29
  • 2012-07-31
  • 1970-01-01
  • 2014-01-14
  • 1970-01-01
  • 1970-01-01
  • 2017-01-16
  • 2020-09-14
  • 1970-01-01
相关资源
最近更新 更多