网站开发日记(6)

google告诉网站站长:您的网络服务器支持 If-Modified-Since HTTP 标头。通过该功能,您的网络服务器可以告诉 Google 自上次抓取您的网站以来,内容是否已发生变化。该功能可以节省您的带宽和开销。

我们来看一下网上对HTTP 头:Last-Modified 与 If-Modified-Since的介绍。(看了两个博客,都没有图片。)

简单的说,Last-Modified 与If-Modified-Since 都是用于记录页面最后修改时间的 HTTP 头信息,只是 Last-Modified 是由服务器往客户端发送的 HTTP 头,而 If-Modified-Since 则是由客户端往服务器发送的头,可 以看到,再次请求本地存在的 cache 页面时,客户端会通过 If-Modified-Since 头将先前服务器端发过来的 Last-Modified 最后修改时间戳发送回去,这是为了让服务器端进行验证,通过这个时间戳判断客户端的页面是否是最新的,如果不是最新的,则返回新的内容,如果是最新的,则 返回 304 告诉客户端其本地 cache 的页面是最新的,于是客户端就可以直接从本地加载页面了,这样在网络上传输的数据就会大大减少,同时也减轻了服务器的负担。想要详细查看 HTTP 头信息,可以在 Firefox 中安装 LiveHTTPHeaders 插件,安装完成之后按 Alt+L 就可以在 Sidebar 中看到了。


在服务器和浏览器打交道的过程中,有几个Header对Cache而言至关重要,分别是

服务器响应头:Last-Modified,Etag
浏览器请求头:If-Modified-Since,If-None-Match

服务器发出Etag,Last-Modified头后,下次浏览器再进行同样的请求,则会发出If-None-Match,If-Modified-Since头,而后服务器根据这些信息来判断是否需要发送数据,如果没有更新,服务器就简单的发送一个304状态告诉浏览器用缓存就OK了,不用下载数据了,从而节约了带宽。

先看看怎么用PHP发出一个Last-Modified头:

header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');

如果你开启了session,那么类似下面的代码也会产生Last-Modified头:

session_cache_limiter('private_no_expire');
session_start();

再看看怎么用PHP发出一个Etag头:

header('Etag: ' . md5($etag));

很简单,类似上面的样子就可以了,你想用什么做为$etag看你自己的选择,比如说某个字符串的md5散列就是一个不错的选择,uuid那样格式的字符串也挺帅,就算是一个类似abcdefg这样的普通字符串也可以,因为HTTP协议没有对Etag的数据格式做特殊要求。

如果浏览器请求的是PHP这样的动态脚本,那么我们就可以用PHP设置必要的Last-Modified,Etag头,当浏览器下次进行同样的请求时,PHP脚本就可以根据浏览器自动反馈的If-Modified-Since,If-None-Match头来排判断是否需要发送内容,如果没有更新,则简单的进行如下操作即可:

header('HTTP/1.0 304 Not Modified');
exit;

浏览器不用再下载数据,而是直接启用缓存。

再来看看如果浏览器请求的静态内容(如js, css, image等)会怎么样。缺省状态下,Apache会对静态文件的响应都会自动添加Last-Modified,Etag头,其中Etag的具体值由文件的索引节点、大小、最后修改时间决定,相当于httpd.conf里的如下配置:

FileETag INode Size MTime

不过这样的设置在某些情况下会出问题:比如说你的Web前端采用的DNS轮循,把请求分布到不同的服务器上,那么对同一个静态文件的请求,在不同的服务器上势必会生成不同的Etag值,因为它们的INode是不同的。

所以,为了避免同一个文件在不同服务器上的ETag不同,我们要去掉INode的影响:

FileETag Size MTime

但就算是这样的设置你也必须小心,因为你还得保证各个服务器的时间是同步的,否则MTime也会造成Etag的不一致。

---------------------------

后记:

什么时候适合采用这样的技术呢?答案是当你总想知道某些东西是否有更新的时候,这个技术的价值就显现出来了。比如说RSS在线阅读器。不过也有例外,像在线股票信息,这东西几乎每时每刻都在更新,浏览器缓存这时候就不需要了。

你可能感兴趣的:(PHP,cache,浏览器,网络协议,Google)