Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

使用ETag缓存减少网络开销

  现在HTTP协议的发展已经很完善了,很多需求在HTTP协议中都已经被支持。比如页面缓存这个需求,HTTP就提供了多种缓存功能。最常用的就是超时缓存,设置一个时间,在该时间段内浏览器使用缓存的数据而不向服务器发起请求。这种模式对服务器而言是最省心的,因为不访问服务器所以可以大大减少服务器的性能开销。但是这种缓存方式也有弊端,比如设置了缓存后就无法从服务器获取到最新的数据。所以在实际应用中我们还需要其他缓存方式来解决各种问题。ETag缓存就是为了解决这个问题而被提出的,但是它不能减少服务器性能上的开销,不过它可以有效的减少带宽的占用。
  ETag的工作原理就是让服务器对向客户端发送的数据添加一个标识符,当页面内容发生变化时标识符也会随着变化。客户端向服务器发起请求的时候带上这个标识符,如果标识符没有变化就说明页面内容没有变化。这时候服务器就可以给客户端返回一个304状态码并断开连接,这样就不用从服务器上把庞大的页面数据再次发送给客户端了。只有当服务器判断客户端发送过来的标识符和新生成的标识符不同时,服务器才会把新的数据发送到客户端,并返回一个200状态码。

  很多Web服务器都对静态资源默认启用了ETag,但是动态资源服务器本身就无力了。所以我们需要在程序中来控制。ETag没有固定的格式,一般用页面数据的MD5就可以了。下面是一段PHP实现ETag的代码。
//开启ob,让输出的数据写入缓冲区
ob_start();

//此处是页面的代码
//这里用当前分钟数做测试
echo time()/60|0;

//读取ob缓冲区的所有数据
$s=ob_get_contents();
//关闭ob,并清空缓冲区
ob_end_clean();
//生成ETag
$ETag=md5($s);
//判断客户端请求的ETag是否和当前页面的ETag相同
if($_SERVER['HTTP_IF_NONE_MATCH']==$ETag){
  //如果相同则返回304状态码
  header('HTTP/1.1 304 Not Modified');
}else{
  //如果不相同则带上新的ETag,并输出页面数据
  header('ETag:'.$ETag);
  echo $s;
};
  这样,首次访问的时候是200的状态码,而之后访问则是304。

  需要注意的是服务器发送给客户端的ETag是使用HTTP头的ETag字段,而客户端使用这个ETag请求服务器的时候使用的是If-None-Math字段。这个在上面的HTTP请求信息中可以看到。所以PHP程序里需要使用HTTP_IF_NONE_MATCH来获取客户端提交过来的ETag。
  类似的,还有Last-Modified,是使用文件的最后修改事件作为判断的,它不需要调用计算MD5,可以给服务器减轻一些负担。不过如果是动态页就不存在最后修改时间这个说法,所以通用性不如ETag。不过它也有自己的作用,以后再来说说它吧。
网名:
3.80.55.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^