HTTP 状态码 200(缓存)与状态码 304 有啥区别?
Posted
技术标签:
【中文标题】HTTP 状态码 200(缓存)与状态码 304 有啥区别?【英文标题】:What is the difference between HTTP status code 200 (cache) vs status code 304?HTTP 状态码 200(缓存)与状态码 304 有什么区别? 【发布时间】:2010-12-12 12:18:46 【问题描述】:我正在使用 Firefox 的 Google“Page Speed”插件来访问我的网站。
我页面上的一些组件被指示为 HTTP 状态:
200 200(缓存) 304
通过 Google 的“页面速度”。
我很困惑的是 200(缓存)和 304 之间的区别。
我已经多次刷新页面(但没有清除我的缓存),我的 favicon.ico 和一些图像似乎总是 status=200(缓存),而其他一些图像是 http 状态 304。
我不明白为什么会有差异。
更新:
使用 Google“Page Speed”,我收到 http://example.com/favicon.ico 和 http://cdn.example.com/js/ga.js 的“200(缓存)”
但是,我收到http://cdn.example.com/js/combined.min.js 的 http 状态“304”
我不明白为什么我有两个 javascript 文件位于同一目录 /js/ 中,一个返回 http 状态 304,另一个返回 200(缓存)状态代码。
【问题讨论】:
【参考方案1】:代码为“200(缓存)”的项目直接从您的浏览器缓存中完成,这意味着对项目的原始请求返回的标头表明浏览器可以缓存它们(例如,未来日期Expires
或@ 987654324@ headers),并且在您触发新请求时,那些缓存的对象仍然存储在本地缓存中并且尚未过期。
另一方面,304 是在浏览器检查文件自其缓存的上一个版本以来是否被修改后服务器的响应(答案为“否”)。
为了获得最佳的网络性能,您最好为所有资产设置一个遥远的未来 Expires:
或 Cache-Control: max-age
标头,然后在需要更改资产时,更改资产的实际文件名或附加请求该资产的版本字符串。这消除了发出任何请求的需要,除非资产已明确从缓存中的版本更改(不需要该 304 响应)。谷歌有more details on correct use of long-term caching。
【讨论】:
那么从速度的角度来看,有什么更好的选择......“200(缓存)”或“304”http状态消息? 200 缓存。这里有一些很好的说明:developer.yahoo.com/performance/rules.html#expires。您希望您的资产有尽可能长的到期时间,但必须在这与您以这种方式失去一定程度的控制权这一事实之间取得平衡。您可以做的一件事是为文件设置长期过期,然后在需要时为这些文件增加资产版本号。例如,您可以在 元素中包含 style.css?v1 并在有更改时增加 style.css?v2。 正义,那么为什么 Firebug 报告 ga.js 从本地缓存(状态 = 200 缓存)中提取,而 combine.min.js 报告 304 http 状态。奇怪的是,这两个文件都是相同的文件类型 (JavaScript) 并且驻留在同一个服务器目录中。您会认为两者都是 200 或 304,并且没有区别 如果age
小于max-age
,则max-age
和age
标头组合也会导致200 个(缓存)结果。一个例外是当用户单击浏览器刷新按钮时,会发送一个 304 标头。
HTML5 Boilerplate 建议不要使用缓存清除的查询字符串方法 - 最好将每个文件的 href
、url,
和 src
引用更改为包含“指纹”(文件的哈希值或简单的递增数字),然后告诉服务器剥离该指纹并仅提供style.css
或其他任何内容。如果您不能在服务器上执行此操作,请让您的构建系统使用指纹重命名实际文件。【参考方案2】:
200 (cache) 表示 Firefox 只是使用本地缓存的版本。这是最快的,因为没有向 Web 服务器发出请求。
304 表示 Firefox 正在向 Web 服务器发送“If-Modified-Since”条件请求。如果自浏览器发送的日期以来该文件还没有更新,Web 服务器会返回一个 304 响应,这实际上是告诉 Firefox 使用其缓存版本。它没有200(缓存)那么快,因为请求仍然发送到Web服务器,但服务器不必发送文件的内容。
关于你的最后一个问题,我不知道为什么同一目录下的两个 JavaScript 文件返回的结果不同。
【讨论】:
【参考方案3】:这也让我很长时间。我要验证的第一件事是您没有通过单击刷新按钮重新加载页面,这将始终发出有条件的资源请求,并且会为许多页面元素返回 304。而是转到 url 栏选择页面并按 Enter 键,就像您刚刚再次输入相同的 URL 一样,这将使您更好地指示哪些内容被正确缓存。这篇文章很好地解释了条件请求和无条件请求之间的区别以及刷新按钮如何影响它们: http://blogs.msdn.com/b/ieinternals/archive/2010/07/08/technical-information-about-conditional-http-requests-and-the-refresh-button.aspx
【讨论】:
我什至无法描述我花了多少时间试图弄清楚对 CDN 的请求的 304 状态。虽然你回答的问题有点不同,但你应该得到赏金:-) 您是对的:代码的差异与您是否正在重新加载页面有关。如果我重新加载页面,我会在浏览器的网络监视器中看到 304 代码。但是,如果我访问另一个使用这些相同文件的 URL,我会在浏览器的网络监视器中看到 200(来自缓存)代码。在我的情况下,另一个 URL 只是附加到原始 URL 的查询字符串(页面是基本相同)。【参考方案4】:HTTP 304 “未修改”。你的网络服务器基本上是在告诉浏览器“这个文件自你上次请求以来没有改变过”。而 HTTP 200 告诉浏览器“这是一个成功的响应” - 当您的浏览器第一次访问文件或第一次访问修改后的副本时应该返回。
有关状态码的更多信息,请查看http://en.wikipedia.org/wiki/List_of_HTTP_status_codes。
【讨论】:
这也是我的理解......这就是为什么我在原始帖子中声明我已经多次刷新我的页面并且仍然为同一个图标获得“200(缓存)”。 ico 和特定的 JavaScript 包括我有。很奇怪 200 实际上并不意味着缓存,它只是意味着 OK。可能是您的服务器配置没有明确告诉浏览器缓存您的 ico 和 js 文件,这将使其返回状态代码 200。 在我的某些 JavaScript 中,b/c 不是这种情况,我收到 304,而其他 JavaScript 我收到“200(缓存)”。所有 JavaScript 都位于同一个 Web 服务器目录 example.com/js/ 我应该补充一下,200(缓存)只是意味着它是在本地缓存的,实际上并不向服务器发出请求,这比去服务器并获得 304 响应要快。跨度> 我已经更新了我的原始帖子以显示我的实时网站和相关的 JavaScript。请参阅我更新的原始帖子。【参考方案5】:最后一个问题,为什么?我会尽量用我知道的来解释
通俗地解释一下这三个状态码。
200 - 成功(浏览器请求并从服务器获取文件)如果在服务器中启用了缓存
200(来自内存缓存)- 在浏览器中找到文件,因此浏览器不会向服务器发出请求 304 - 浏览器请求文件但被服务器拒绝对于某些文件,浏览器决定从服务器请求,而对于某些文件,它决定从存储(缓存)的文件中读取。为什么是这样 ?每个文件都有一个到期日期,所以
如果文件未过期,则浏览器将使用缓存(200 缓存)。
如果文件过期,浏览器会向服务器请求文件。两个地方(浏览器和服务器)的服务器检查文件。如果找到相同的文件,服务器将拒绝该请求。根据协议浏览器使用现有文件。
看看这个nginx配置
location /
add_header Cache-Control must-revalidate;
expires 60;
etag on;
...
这里的过期时间设置为 60 秒,所以所有静态文件都缓存了 60 秒。因此,如果您在 60 秒内再次请求文件,浏览器将从内存(200 内存)中读取。如果您在 60 秒后请求浏览器将请求服务器 (304)。
我假设文件在 60 秒后没有更改,在这种情况下你会得到 200(即,更新的文件将从服务器获取)。
因此,如果服务器配置了不同的过期和缓存标头(策略),则状态可能会有所不同。
在您使用 cdn 的情况下,cdn 的主要目的是高可用性和快速交付。因此他们使用多个服务器。即使文件似乎在同一个目录中,cdn 也可能使用多个服务器来提供您的内容,如果这些服务器具有不同的配置。然后这些状态可以改变。希望对您有所帮助。
【讨论】:
304 - Not Modified 不是服务器的“拒绝”。它是服务器向客户端声明“对于您要求的版本,我知道它没有被修改,您并不真的需要该文件”。从技术上讲,304 是“重定向”响应代码之一。它告诉客户端“从你自己的缓存中获取它”。以上是关于HTTP 状态码 200(缓存)与状态码 304 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章