Answers:
它们略有不同-ETag没有客户端可以用来确定将来是否再次请求该文件的任何信息。如果只有ETag,它将始终必须发出请求。但是,当服务器从客户端请求中读取ETag时,服务器可以确定是发送文件(HTTP 200),还是告诉客户端仅使用其本地副本(HTTP 304)。ETag基本上只是文件的校验和,当文件内容更改时,ETag在语义上也会更改。
客户端(和代理/缓存)使用Expires标头来确定它是否甚至根本不需要向服务器发出请求。您离Expires日期越近,客户端(或代理)从服务器向该文件发出HTTP请求的可能性就越大。
因此,您真正想做的就是使用BOTH标头-根据内容的更改频率将Expires标头设置为合理的值。然后配置要发送的ETag,以便客户端将请求发送到服务器时,它可以更轻松地确定是否将文件发送回。
关于ETag的最后一点说明-如果您在多台运行Apache的计算机上使用负载平衡的服务器设置,则可能需要关闭ETag生成。这是因为inode用作ETag哈希算法的一部分,这在服务器之间会有所不同。您可以将Apache配置为不将inode用作计算的一部分,但随后您要确保文件上的时间戳完全相同,以确保为所有服务器生成相同的ETag。
Expires
并且Cache-Control
是“强缓存头”
Last-Modified
并且ETag
是“弱缓存头”
首先,浏览器检查Expires/Cache-Control
以确定是否向服务器发出请求
如果必须发出请求,它将发送Last-Modified/ETag
HTTP请求。如果Etag
文档的值与之匹配,则服务器将发送304代码而不是200,并且没有内容。浏览器将从其缓存中加载内容。
默认情况下,Apache将基于文件的inode编号,上次修改日期和大小生成一个Etag ,这完全可以满足您的要求。我认为默认情况下,它还会根据磁盘上文件的最后修改时间生成Last-Modified标头,这对于执行您想要的操作也非常合适。
您可能还应该让Apache发送未来一年的Expires标头(根据http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21),以便浏览器知道其内容是可缓存的。看一下mod_expires进行配置。
另一个总结:
您需要同时使用两者。ETag是“服务器端”信息。过期是“客户端”缓存。
除非您有负载平衡的服务器,否则请使用ETag。它们很安全,每当您更改某些内容时,都会让客户端知道他们应该获取服务器文件的新版本。
必须谨慎使用Expires,就像您设置的过期日期很远,但要立即更改其中一个文件(例如JS文件)一样,某些用户可能要等很长时间才能获得修改后的版本!
我还要提及的另一件事是,可能缺少某些答案,这是同时存在ETags
和Expires/Cache-control
标题中的缺点。
根据您的需要,它可能仅在标头中添加额外的字节,这可能会增加数据包,这意味着更多的TCP开销。同样,您应该查看在标头中同时包含这两项的开销是否必要,或者只是在请求中增加额外的权重而降低了性能。
您可以在Kyle Simpson 撰写的精彩博客文章中了解更多相关信息:http : //calendar.perfplanet.com/2010/bloated-request-response-headers/