HTTP缓存参数 中 Etag 的重要性
Etag 在 HTTP1.1 中有介绍,主要的作用就是在 (css file, image, javascript file) 文件后面添加一个唯一的参数(相当于查询参数字符串),Etag 有服务器端生成,并且随着文件的改变而改变,这样浏览器端就会只重新请求获取 Etag发生变化的文件,减少浏览器端数据的流量,加快浏览器的反应速度,重要的是减轻服务器端的压力,所以服务器端 Etag 的实现就比较重要了.
协商缓存并不会节省连接数,但是在缓存生效时,会大幅减小传输内容(304 响应没有正文,一般只有几百字节)
现在我们有个问题为什么要使用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
另外为什么有两个响应头都可以用来实现协商缓存呢?这是因为一开始用的 Last-Modified 有两个问题:1)只能精确到秒,1 秒内的多次变化反映不出来;2)在轮询的负载均衡算法中,如果各机器读到的文件修改时间不一致,有缓存无故失效和缓存不更新的风险。HTTP/1.1 并没有规定 ETag 的生成规则,而一般实现者都是对资源内容做摘要,能解决前面两个问题。
CDN 的回源事件 和 参数过滤 ETAG 的瓜葛
参数过滤 影响
前端人员利用了 Jquery 的 JSONP 功能,会在每个动态请求发出前在的 URL 后面加时间戳。如果没有启用参数过滤,那么时间戳老是变,那么命中率会很低。
因为 CDN 厂商在设置缓存的时候对于 Key 有两种策略,一种是按照文件名,将问号后面的参数去掉。另外一种是将所有的参数作为缓存 Key 的一部分。 然而,CDN 默认为第二种。由于这个动态时间戳在业务上来说其实是没有用的,因此,果断让前端人员去掉。
CDN 厂商 对 ETAG 处理方式 影响
1. 根据请求过来的Key去查找缓存,没有则回源
2. 如果有则判断浏览器传过来的 etag ,与缓存里面的 etag 作比对,如果发现不同就去回源更新。如果相同就返回状态码304来减少网络传输。
分析
但是只要 CDN 回源更新了就会导致浏览器的 etag 与 CDN 持有的 etag 不同,而 CDN 发现 etag 不匹配就认为资源发生变化,就去回源,而回源的结果就是 etag 又一次的更新,如果访问量很大,那么某一用户的请求更新了 cdn 的 etag 后,其他用户的浏览器未更新持有原来的 etag,那么他和 cdn 的 etag 肯定不同,所以当他请求的时候,又一次需要回源,如此类推,就会导致回源率特别高。
按照etag的规范,服务器判断 etag 是否同客户端传来的 etag 匹配,如果不匹配则返回新的内容和不同的 etag,否则返回304告诉浏览器原来的内容依然有效,还可以使用,就不用传输内容了。
根据以上原则,cdn 厂商的处理方式导致了回源率的升高。
实际上与 etag 类似的 header 字段还有 Last-Modified。但是按照协议规范etag会优先启用。因为他更加的精确。但是如果改变在秒级别以上,完全可以用 Last-Modified 替代 etag。所以让运维将整个站点的etag头都去掉了。 过几分钟观察,回源情一直下降,最后下降到几十个。
注意:
Last-Modified 也有他的局限性,一个是秒级,一个是在轮询的负载均衡算法中,如果各机器读到的文件修改时间不一致,有缓存无故失效和缓存不更新的风险
还有是就是本文中 cdn 厂商对etag 的处理方式,不代表所有的 cdn 厂商都这样。具体还是需要自己去测试一下。我用的腾讯cdn 就已经默认抹除了 etag 。所以不存在本文所说的情况发生。
摘自:https://blog.csdn.net/lgreckey/article/details/84757415
共 0 条评论