php centos wordpress shell Firefox linux Android 微软 mysql 程序员 Ubuntu apache nginx linux命令 HTML5 google Python Windows java 开源

网站前端优化Etag or not ?

Google的PageSpeed网站优化理论中提到使用Etag可以减少服务器负担。https://developers.google.com/speed/docs/pss/AddEtags

而yahoo的Yslow法则中则建议关闭Etag。http://developer.yahoo.com/performance/rules.html#etags

 难道有冲突?其实不然,仔细推敲一下我们发现,Yahoo并没有直接建议我们直接关闭ETag,而是说如果不能合理利用Etag验证模式,那么还不如直接关闭。因此他用了一个词语misconfigured。

可能某些翻译会有一定的误导,例如下面这个链接:http://bbs.linuxtone.org/thread-2620-1-1.html

 什么是Etag ?

Etag 是URL的Entity Tag,用于标示URL对象是否改变。

为什么要使用Etag?

Etag主要为了解决last-Modified无法解决的一些问题.他能比Last_Modified更加精确的知道文件是否被修改过.如果有个文件修改非常频繁,比如在秒以下的时间内进行修改,比如1秒内修改了10次,If-Modified-Since能检查只能秒级的修改,所以这种修改无法判断.原因是UNIX记录MTIME只能精确到秒.所以我们选择生成Etag,因为Etag可以综合Inode,MTime和Size,可以避免这个问题.

Etag的工作原理

Etag在服务器上生成后,客户端通过If-Match或者说If-None-Match这个条件判断请求来验证资源是否修改.我们常见的是使用If-None-Match.请求一个文件的流程可能如下:

新的请求

客户端发起HTTP GET请求一个文件(css ,image,js);服务器处理请求,返回文件内容和一堆Header(包括Etag,例如”2e681a-6-5d044840″),http头状态码为为200.

同一个用户第二次这个文件的请求

客户端在一次发起HTTP GET请求一个文件,注意这个时候客户端同时发送一个If-None-Match头,这个头中会包括上次这个文件的Etag(例如”2e681a-6-5d044840″),这时服务器判断发送过来的Etag和自己计算出来的Etag,因此If-None-Match为False,不返回200,返回304,客户端继续使用本地缓存;

注意.服务器又设置了Cache-Control:max-age和Expires时,会同时使用,也就是说在完全匹配If-Modified-Since和If-None-Match即检查完修改时间和Etag之后,服务器才能返回304.

那么这是个好东西,为什么很多人建议关闭它呢?

主要好是因为他的默认配置。

在Apache的默认配置中ETag是这样定义的:

FileETag INode MTime Size

这几个值分别表示 文件的索引节点(inode)数 ,文件的最后修改日期及时间和 文件的字节数

里面有个inode,这就不难理解了,当后端有多台服务器时(集群方式)根本无法保证inode是一致的。

 那怎么办呢?

1.  去掉ETag    FileETag None
2.  修改ETag参数 例如   FileETag  MTime Size

 这是Apache和Linux,在windows和IIS中同样存在这个问题

IIS是这样来配置Etag的  Filetimestamp:ChangeNumber这里面的ChangeNumber,同样也无法保证一致。

微软的这篇文章表述了如何关闭IIS的ETag。http://support.microsoft.com/?id=922733

延伸阅读

评论