前端杂谈 · Web

前端性能优化 设置 ETags 来控制缓存

•̀.̫•́✧ · 5月1日 · 2020年本文1466字 · 阅读4分钟39

实体标签(ETags),是服务器和浏览器用来决定浏览器缓存中组件与源服务器中的组件是否匹配的一种机制(“实体”也就是组件:图片,脚本,样式表等等)。添加ETags可以提供一种实体验证机制,比最后修改日期更加灵活。一个ETag是一个字符串,作为一个组件某一具体版本的唯一标识符。唯一的格式约束是字符串必须用引号括起来,源服务器用相应头中的ETag来指定组件的ETag。

HTTP/1.1 200 OK
      Last-Modified: Tue, 12 Dec 2006 03:03:59 GMT
      ETag: "10c24bc-4ab-457e1c1f"
      Content-Length: 12195
前端性能优化  设置 ETags 来控制缓存-歪?是3.1415926吗

然后,如果浏览器必须验证一个组件,它用If-None-Match请求头来把ETag传回源服务器。如果ETags匹配成功,会返回一个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
0 条回应