HTTP缓存控制
麦子:听说启用客户端缓存可以减轻服务器的压力,提高网站的吞吐,那具体是怎么回事呢?
栗子:没错,HTTP协议通过一些头信息在服务器和浏览器之间传递关于客户端缓存的信息,使其缓存在浏览器端,浏览器在下次访问的时候,便可以直接从客户的电脑上访问,而不用从服务器上下载,这样就减轻了服务器的压力,而且还使页面更快速的展示出来。
麦子:那对于服务器显示控制的缓存有时间限制吗?
栗子:这个需要根据业务决定了,比如一般网站的LOGO、新闻页面配套的图片很少发生变化,所以缓存时间可以设置的时间长一些。
通过Cache-control: max-age=指定的秒数,
上面这个头来控制缓存的时间,下面我们一起通过一个栗子看一下。
首先我们在nginx中显示的给一个文件设置头信息,使其在客户端缓存30秒:
这次我们使用Firefox的F12看一下请求收到的报文如下:
然后我们在30秒之内再次访问此页面:
通过观察,我们发现,这时浏览器并没有发送任何请求,而是直接从浏览器中读取的。
最后在30秒之后,我们再次访问此页面,发现浏览器重新发送了请求去和服务器端进行鲜活比较,在这个例子中,由于服务器端的文件并没有发生任何改动,所以返回304,如下:
关于控制缓存时间还有Expires头,但其设置的是过期日期,一般不推荐使用,这里就不再举例子了。
麦子:那如果缓存的文件过期了怎么办呢?
栗子:通过文件的修改时间或生成的ETag来决定,下面我们通过实际的例子看一下。
为了实验方便,我们在本地通过nginx部署一个站点(nginx的操作,我们在以后的文章中会详细说到),服务器地址是1.1.1.1,我们用Chrome的F12手抓到的响应包如下:
图中包含了两个字段,一个是index.html文件的最新修改时间:Last-Modified字段,我们用ll查看下index.html的最新修改时间,发现二者是一致的(浏览器返回的是GMT格式的时间,所以要减去8小时)
另外一个字段是Etag,这个是根据文件的内容生成的
好,这时我们不修改服务器上页面,然后让浏览器再次打开index.html,我们一起看下请求和回发的报文:
我们发现服务器返回的状态码是304,表明服务器上的文件没有发生改变,可以直接从本地获取副本,所以服务器只返回了头信息,而没有返回主体内容,这样就节省了网络流量,降低了传输时间。
那服务器上怎么知道浏览器缓存的副本和服务器上当时的文本是一致的呢?这就得从上图Request Headers请求头中的两个字段说起了。我们先来看If-Modified-Since,这个字段的值恰恰就是刚才我们第一次请求index.html返回的头信息中Last-Modified字段的值,这就为服务器是否返回数据内容提供了依据,即根据文件的修改时间进行判断。我们可以试验一下:
先用touch命令修改下index.html的“修改时间”为当前时间
然后我们再次使用浏览器访问页面,这时虽然页面的内容没有改变,但由于“修改时间”发生了变化,使浏览器提供的If-Modified-Since和服务器的Last-Modified产生了不一致,所以服务器返回了index.html的所有内容,如下图示: