雅虎前端优化总结的35 条前端性能优化军规第十三条:设置 ETags 来控制缓存。实体标记(Entity tags,ETag)是服务器和浏览器之间判断浏览器缓存中某个文件是否匹配服务器端原文件的一种机制。实体就是资源文件,如图片,脚本,样式等等。ETag 是比验证 last-modified
日期更高效的机制。
服务器这样设置组件的 ETag:
HTTP/1.1 200 OK
Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
ETag: "10c24bc-4ab-457e1c1f"
Content-Length: 12195
之后,如果浏览器要验证文件,它用 If-None-Match
头部来传 ETag 给服务器。如果 ETag 匹配,服务器返回 304(文件未变化),就不下载内容。这样就减少了 12195 个字节的响应体。Etag 通过文件版本标识,方便服务器判断请求的内容是否有更新,如果没有就响应 304,避免重新下载:
GET /i/yahoo.gif HTTP/1.1
Host: us.yimg.com
If-Modified-Since: Tue, 12 Dec 2006 03:03:59 GMT
If-None-Match: "10c24bc-4ab-457e1c1f"
HTTP/1.1 304 Not Modified
ETag 的问题在于,通常使用文件的某些属性来构造它,这些属性对于特定的网站服务器来说是唯一的。在集群的情况下,当浏览器从一台服务器上获取了原始文件之后又尝试向另一台服务器来验证文件时,ETag 是不匹配的。这种情况是使用服务器集群的网站经常会遇到的问题。默认情况下,Apache 和 IIS 向 ETag 中嵌入的数据都会大大降低有效性验证的成功率。
Apache1.3 和 2.x 的 ETag 格式是 inode-size-timestamp
。文件系统使用 inode 来存储诸如文件类型、所有者、组和访问模式等信息。尽管在多台服务器上一个给定的文件可能位于相同的目录、具有相同的文件大小、权限、时间戳等,从一台服务器到另一台服务器的 inode
仍然是不同的。
IIS5.0 和 6.0 在 ETag 上有着类似的问题。IIS 上 ETag 的格式是 Filetimestamp:ChangeNumber
。ChangeNumber
适用于跟踪 IIS 配置变化的计数器。对于一个网站背后的所有 IIS 服务器来说,ChangeNumber
不大可能相同。
最终的结果是,对于完全相同的组件,从一台服务器到另一台,Apache 和 IIS 产生的 ETag 是不会匹配的。如果 ETag 不匹配,用户就不会按照 ETag 的设计那样接收到更小更快的 304 响应;相反,它们会收到普通的 200 响应以及组件的所有数据。
如果只在一台服务器上部署网站,这通常不会产生问题;但如果使用了服务器集群,同时使用 Apache 或者 IIS 默认的 ETag 配置,用户响应将变慢,服务器负载将变高,将消耗更多的带宽,同时代理缓存的效率也会下降。即使组件具有长久的 Expires 头,一旦用户单击了 Reload 或 Refresh 按钮,依然会产生条件 GET 请求。
如果组件必须通过最新修改日期之外的一些东西来进行验证,则 ETag 是一种强大的方法;如果无须自定义 ETag,则最好将其移除。 last-modified
头基于文件的时间戳进行验证,可以提供完全等价的信息,而且移除 ETag 可以减少响应和后续请求的 HTTP 头的大小。在 Apache 中,只要向 Apache 配置文件中简单地添加下面一行配置就能移除 ETag:
FileETag none