论坛首页 Web前端技术论坛

HTTP协议缓存策略深入详解之etag妙用

浏览 22958 次
精华帖 (2) :: 良好帖 (9) :: 新手帖 (2) :: 隐藏帖 (1)
作者 正文
   发表时间:2010-04-30   最后修改:2010-04-30

Etag是什么:

Etag 是URL的Entity Tag,用于标示URL对象是否改变,区分不同语言和Session等等。具体内部含义是使服务器控制的,就像Cookie那样。

  HTTP协议规格说明定义ETag为“被请求变量的实体值” 。另一种说法是,ETag是一个可以与Web资源关联的记号(token)。典型的Web资源可以一个Web页,但也可能是JSON或XML文档。服务器单独负责判断记号是什么及其含义,并在HTTP响应头中将其传送到客户端。

 

实例详解:

也许读者们看完这个概念,还是搞不清楚这个etag响应头消息到底是干什么的,具体如何使用,所以接下来的篇幅我会用一个实际的例子来详细阐述etag的妙用。

 

 

想必许多网友都有订阅某些大虾的RSS的习惯吧,但是大虾也是人,也要吃饭睡觉打豆豆,所以不可能无时无刻的在从事文学创作,因此一般产量较高的大虾也许平均每天能更新两篇已经是不错了,但是网友们却总是不断的去刷新RSS订阅的内容,期望在下次刷新中又有新的劲爆文章出现,如果我们每次刷新,都要从服务器端重新获取内容(事实上,几乎一天内95%以上的刷新返回的都是相同内容,因为刚才也说了,大虾一般一天也就出一两篇新文章而已,所以大部分时间内,内容都是相同的),如果订阅量相当巨大,这对于服务器的压力还是带宽都是一个严重的挑战。其实真正需要服务器重新返回内容是大虾们更新了新的文章后,而其他时间我们无论怎么刷新服务器最好能做到不需返回任何数据,这才是一个比较好的方案,而我们的主角etag响应头的出现正是为了解决这个问题。

 

 

浏览器端实现

 

当我们订阅了某大虾的RSS,如图,我们点击左下角“RSS”按钮:


然后我们进入了rss订阅的相关页面,此时我们打开tamper data查看下http请求和响应的一些内容(这里我们截获http请求和响应信息的工具是基于FF浏览器的tamper data插件,如果您对这个插件不熟悉,请参考我的另外一篇介绍该工具的文章--  Tamper Data安装与使用简介 )。如下图:

 


从上图我们可以看到,服务器端返回响应值为200,并发送回了相应的网页内容,在http响应头中有etag消息头,值为

Etag="fca75d26f6dc8111a7d1b24e9debd652",我们不需要去关心这个响应头的内容是什么,我们只需要将这这个

头信息的值记录下来,随便创建一个notepad之类的东西保存好,以备接下来的实验使用。

 

然后我们刷新,希望能从webserver端获取该大虾新的文章,这时候我们用tamper data查看下http头中有哪些内容,如下图:

 

 

从此图中我们可以看到If-None-Match="fca75d26f6dc8111a7d1b24e9debd652",而该值的内容和我们先前第一次

刷新返回的http响应中的etag响应头的值完全一样。

 

如果某大虾并没在这段时间内发表任何文章,于是webserver端的rss文件没有任何变化,于是If-None-Match值和server端

的etag值相比较完全相等,这时候服务器就会认为客户端已经有最新的rss文件内容的缓存了,于是服务器就会发送一个 响应码

为“304”的http响应,304响应想必大家都知道是什么意思了,没错,他不包含任何响应的内容,只是提示客户端缓存的内容是最新的,

如下图


 

 

如果某大虾刚发表了一篇新的文章,因此在webserver中的rss的内容发生了改变,因此他的etag值就会发生改变,于是服务器会拿http请求中的If-None-Match的

值和改变和的etag值做对比,显然不正确的,于是webserver就会发送一个新的rss内容给客户端,这里我不能强制要求某大虾来配合我们的实验去立马发表新文章,

所以我们就变相做,也就是我们故意修改http请求头中的If-None-Match的值,这样就和服务器端的etag就不会匹配了,显然这时候服务器就会受骗发送一份“新”的

rss内容回来,如下图:

 

 

 

 

 

这里我们将http请求中的If-None-Match的值改为了"modifiedForOurTest", 显然与响应中的Etag="fca75d26f6dc8111a7d1b24e9debd652"不同,因此服务器就被受骗认为浏览器没有最新的文件内容,于是就返回了全新的响应内容(状态码200),而事实上浏览器端是有最新的内容的缓存的。

 

 

结束语:

 

 好了,到这里,对这个etag响应头的讲解就结束了,如果反应不错,下一篇我们将介绍并实例详解cache-control的用法,敬请期待:)

 

 

 

 

 

 

 

 

  • 大小: 38.4 KB
  • 大小: 99.6 KB
  • 大小: 29.3 KB
  • 大小: 21 KB
  • 大小: 85.8 KB
   发表时间:2010-05-05  
图文并茂,很不错
一个古老的HTTP协议确实有太多的细节大家没有注意,但却又是那么重要~~
0 请登录后投票
   发表时间:2010-05-06  
请问ls大侠,就算知道了HTTP协议缓存策略中的etag是怎么回事,对我们的实际开发也没什么帮助啊!
0 请登录后投票
   发表时间:2010-05-06  
顶一个,这种知识拾遗式学习还是不错的。。。
期待更多。。
0 请登录后投票
   发表时间:2010-05-07   最后修改:2010-05-07
Http1.1中提供了Etag的校验方式。apache1.3和2.x的Etag格式是:inode-size-timestamp。IIS5.0和6.0的Etag格式为Filetimestamp:Changenumber。而对于有CDN网络的网站来说,不同服务器之间的Etag是不同的。

详细可以看,http://www.w2blog.net/view/495.html
0 请登录后投票
   发表时间:2010-05-07   最后修改:2010-05-07
的确, etag码的生成和具体的服务器是有直接的关联的,如果浏览器端前后两个http请求的接收端为不同的地址的服务器,那返回的etag都是各自生成的不同的,所以就没法起到很好的缓存作用,这也是etag应用中一个比较难以解决的问题吧。。。 所以如果项目只有一台服务器,用etag是没任何问题的, 如果是大于一台以上服务器,如大规模集群之类的,最好的方法还是移除etag,只使用Last-Modified就足够了。
0 请登录后投票
   发表时间:2010-06-02  
传说の黄花菜 写道
的确, etag码的生成和具体的服务器是有直接的关联的,如果浏览器端前后两个http请求的接收端为不同的地址的服务器,那返回的etag都是各自生成的不同的,所以就没法起到很好的缓存作用,这也是etag应用中一个比较难以解决的问题吧。。。 所以如果项目只有一台服务器,用etag是没任何问题的, 如果是大于一台以上服务器,如大规模集群之类的,最好的方法还是移除etag,只使用Last-Modified就足够了。

恰恰相反,集群环境下,应该舍弃Last-Modified而用etag。

Last-Modified存在的问题:
1、各个服务器上的文件时间可能不同,或者同一服务器不同路径的相同文件也时间不同。
2、如果用旧文件覆盖新文件,因为时间更前,浏览器不会请求这个更旧的文件。


各个服务器上的文件时间可能不同,但相同内容的etag应该相同,只要内容相同,即使在不同的服务器,不同的路径,etag都相同。可以自定义设计一个etag的算法来控制。
0 请登录后投票
   发表时间:2010-06-02   最后修改:2010-06-02
附带说一句,我有一段时间完整的研究了一下http协议规范,发现http标准还没有被浏览器完全支持,其中Opera可能是支持最为完整的,IE最差。
比如 multiple responses ,一个请求多个返回,很好的想法,IE还不支持。
0 请登录后投票
   发表时间:2010-06-02  
      Apache 1.3和2.x中的ETag格式为inode-size-timestamp。即使某个文件在不同的服务器上会处于相同的目录下,文件大小、权限、时间戳等都完全相同,但是在不同服务器上他们的内码也是不同的。
      IIS 5.0和IIS 6.0处理ETag的机制相似。IIS中的ETag格式为Filetimestamp:ChangeNumber。用ChangeNumber来跟踪IIS配置的改变。网站所用的不同IIS服务器间ChangeNumber也不相同。 不同的服务器上的Apache和IIS即使对于完全相同的内容产生的ETag在也不相同,用户并不会接收到一个小而快的304响应;相反他们会接收一个正常的200响应并下载全部内容。如果你的网站只放在一台服务器上,就不会存在这个问题。但是如果你的网站是架设在多个服务器上,并且使用Apache和IIS产生默认的ETag配置,你的用户获得页面就会相对慢一点,服务器会传输更多的内容,占用更多的带宽,代理也不会有效地缓存你的网站内容。即使你的内容拥有Expires文件头,无论用户什么时候点击“刷新”或者“重载”按钮都会发送相应的GET请求。
      如果你没有使用ETag提供的灵活的验证模式,那么干脆把所有的ETag都去掉会更好。
0 请登录后投票
   发表时间:2010-11-11  
楼主写的很好,一下子就看明白了,赞一个。
0 请登录后投票
论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics