ETag vs标头过期


359

我环顾四周,但无法弄清楚是否应该同时使用ETag Expires标头两者之一。

我要尝试做的是确保我的Flash文件(以及其他图像,以及仅在这些文件发生更改时才更新的文件)。

我不想做任何特殊的事情,例如更改文件名或在URL的末尾添加一些奇怪的字符,以使其不被缓存。

另外,我到底需要在PHP脚本中以编程方式来做些什么来支持这一点,还是全部都是Apache?


Answers:


677

它们略有不同-ETag没有客户端可以用来确定将来是否再次请求该文件的任何信息。如果只有ETag,它将始终必须发出请求。但是,当服务器从客户端请求中读取ETag时,服务器可以确定是发送文件(HTTP 200),还是告诉客户端仅使用其本地副本(HTTP 304)。ETag基本上只是文件的校验和,当文件内容更改时,ETag在语义上也会更改。

客户端(和代理/缓存)使用Expires标头来确定它是否甚至根本不需要向服务器发出请求。您离Expires日期越近,客户端(或代理)从服务器向该文件发出HTTP请求的可能性就越大。

因此,您真正想做的就是使用BOTH标头-根据内容的更改频率将Expires标头设置为合理的值。然后配置要发送的ETag,以便客户端将请求发送到服务器时,它可以更轻松地确定是否将文件发送回。

关于ETag的最后一点说明-如果您在多台运行Apache的计算机上使用负载平衡的服务器设置,则可能需要关闭ETag生成。这是因为inode用作ETag哈希算法的一部分,这在服务器之间会有所不同。您可以将Apache配置为不将inode用作计算的一部分,但随后您要确保文件上的时间戳完全相同,以确保为所有服务器生成相同的ETag。


12
您还应该检查是否应使用Cache-Control而不是Expires。我的理解是Cache-Control是在Expires之后引入的,可以为您提供更多控制权。参见stackoverflow.com/questions/5799906/…–
路易斯·佩雷斯

6
使用Expires标头时,最好的做法是在资源更改时更改文件名,因为客户端不会在文件过时之前再次请求文件。特别是如果您使用远期值作为到期日期。
schnatterer 2014年

8
可以说我们将同时使用两者。过期时间到期但文件未更改(Etag相同)时会发生什么?服务器将返回304,文件将从浏览器缓存中提供。我的问题是,这时会重新生成Expire时间吗?
user345602

2
注意将ETAG Expires标头设置为非零值。这可能会导致比赛条件。参见jakearchibald.com/2016/caching-best-practices
Weston

2
是否可以告诉服务器根本不使用索引节点或时间戳?另外,如果ETag仅用于表示内容,为什么还要使用它们呢?
Seza

108

EtagLast-modified标头是验证器

它们帮助浏览器和/或缓存(反向代理)了解文件/页面是否已更改,即使它保留了相同的名称。

ExpiresCache-control提供刷新信息

这意味着它们可以告知浏览器和反向代理之间的关系,最多可以通知他们何时将页面/文件保留在其缓存中。

因此,问题通常是要使用哪个验证器(etag)或最后修改的验证器,以及要使用的哪个刷新信息头,到期或缓存控制。


30

Expires并且Cache-Control是“强缓存头”

Last-Modified并且ETag是“弱缓存头”

首先,浏览器检查Expires/Cache-Control以确定是否向服务器发出请求

如果必须发出请求,它将发送Last-Modified/ETagHTTP请求。如果Etag文档的值与之匹配,则服务器将发送304代码而不是200,并且没有内容。浏览器将从其缓存中加载内容。


1
您是否找到任何文档支持“强弱”缓存行为?我找不到一个,并且我的客户端浏览器现在将最后修改的优先级实际上确定为过期,这我不理解为什么。
GMsoF 2015年

1
@GMsoF您可能需要看一下:tools.ietf.org/html/rfc7232#section-2.1
Medeiros,

因此,如果我想确保我的更改立即传播到客户端,但仍然有益于某些缓存,那么我只能使用Last-Modified和ETag对吗?
塞巴斯蒂安·洛伯

18

默认情况下,Apache将基于文件的inode编号,上次修改日期和大小生成一个Etag ,这完全可以满足您的要求。我认为默认情况下,它还会根据磁盘上文件的最后修改时间生成Last-Modified标头,这对于执行您想要的操作也非常合适。

您可能还应该让Apache发送未来一年的Expires标头(根据http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21),以便浏览器知道其内容是可缓存的。看一下mod_expires进行配置。


因此,ETag将进行最后修改,expires标头将告诉它我要对其进行缓存,并且当我上传并覆盖文件时,它将再次被拉至用户的缓存中,否则会生成304吗?
GeoffreyF67

Etag的复杂程度取决于上次修改的日期。但是当您修改文件时,Etag将会更改。然后,浏览器发送的Etag(针对文件的缓存版本)将与服务器上文件的Etag不匹配,并且Apache将发送文件而不是304响应。
David Z

6
一年到期标头会不会告诉客户甚至一年都不检查新版本?
John Bachir

@John:是的,我想我在想静态内容,当我写静态内容时,它永远不会改变。
David Z

2
@John Bachir:应该具有特殊的行为,但是无论如何浏览器似乎都至少会命中服务器,以询问更新的版本。我打开了另外一个问题这个问题:stackoverflow.com/questions/10048740/...
马尔科Demaio

13

另一个总结:

您需要同时使用两者。ETag是“服务器端”信息。过期是“客户端”缓存。

  • 除非您有负载平衡的服务器,否则请使用ETag。它们很安全,每当您更改某些内容时,都会让客户端知道他们应该获取服务器文件的新版本。

  • 必须谨慎使用Expires,就像您设置的过期日期很远,但要立即更改其中一个文件(例如JS文件)一样,某些用户可能要等很长时间才能获得修改后的版本!


2
在这种情况下,您基本上需要重命名js并在HTML中进行更改,并希望您也没有将HTML文件的过期时间设置为1年。
EralpB

1

我还要提及的另一件事是,可能缺少某些答案,这是同时存在ETagsExpires/Cache-control标题中的缺点。

根据您的需要,它可能仅在标头中添加额外的字节,这可能会增加数据包,这意味着更多的TCP开销。同样,您应该查看在标头中同时包含这两项的开销是否必要,或者只是在请求中增加额外的权重而降低了性能。

您可以在Kyle Simpson 撰写的精彩博客文章中了解更多相关信息:http : //calendar.perfplanet.com/2010/bloated-request-response-headers/


1

在我看来,使用Expire Header,服务器可以告诉客户端我的数据何时会过时,而使用Etag,服务器可以检查客户端的每个请求的etag值。


0

ETag用于确定资源是否应使用副本一。像Cache-Control这样的Expires Header被告知客户端,在缓存数十年之前,客户端应获取本地资源。

在现代站点中,通常会提供一个名为hash的文件,例如app.98a3cf23.js,因此使用Expires Header是一个好习惯。除此之外,它还降低了网络成本。

希望能帮助到你 ;)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.