最佳实践9:理解HTTP协议中的缓存控制:服务器端缓存控制头部信息
HTTP协议采用客户端请求(Request)、服务器端响应(Response)的模型。在请求和响应中,都能通过相关控制指令对对端的缓存行为进行管理。首先需要关心的是,服务器端响应中的缓存控制头部,利用这些头部控制信息可以精细化地管理客户端的缓存行为。
下面使用wget命令来看一个简单的例子。
# wget -S http://10.1.6.28/test.jpg #使用-S参数,指定显示响应头部信息 --2016-01-08 15:47:29-- http://10.1.6.28/test.jpg Connecting to 10.1.6.28:80... connected. HTTP request sent, awaiting response... HTTP/1.1 200 OK Server: nginx/1.9.7 Date: Fri, 08 Jan 2016 07:47:28 GMT Content-Type: image/jpeg Content-Length: 20305 Last-Modified: Fri, 08 Jan 2016 07:25:26 GMT ① Connection: keep-alive ETag: "568f6466-4f51" ② Expires: Sat, 09 Jan 2016 07:47:28 GMT ③ Cache-Control: max-age=86400 ④ Accept-Ranges: bytes Length: 20305 (20K) [image/jpeg] Saving to: `test.jpg' 100%[===================================================================================================>] 20,305 --.-K/s in 0s 2016-01-08 15:47:29 (137 MB/s) - `test.jpg' saved [20305/20305]
在该实例中,服务器端使用到了4个指令来控制缓存。
·Last-Modified:Fri,08 Jan 201607:25:26 GMT表示该文件的最后修改时间是Fri,08 Jan 201607:25:26 GMT。客户端在后续需要请求该文件时,使用对应的请求头部If-Modified-Since:Fri,08 Jan 201607:25:26 GMT就可以验证服务器端文件是否发生变化。可以使用如下命令进行验证:
wget --header='If-Modified-Since: Fri, 08 Jan 2016 07:25:26 GMT' -S http://10.1.6.28/test.jpg
如服务器端文件未在此时间后发生变化,则服务器端不需要重新发送整个文件,而只需要发送“304 Not Modified”通知客户端即可。此时可以节省传输该文件的带宽和时间。
·ETag:"568f6466-4f51"相当于该静态资源的身份ID。在Web服务器Nginx中,ETag的值是基于文件的最后修改时间(时间戳)和文件大小(字节)计算出来的。浏览器在下一次请求该资源的过程中,使用If-None-Match:"568f6466-4f51"即可确认该资源是否发生了变化。服务器端再次验证,如果未变化,则直接返回给客户端HTTP/1.1304 Not Modified,而不需要再次传输整个文件,起到缓存的效果。如下所示:
# wget --header='If-None-Match: "568f6466-4f51"' -S http://10.1.6.28/test.jpg --2016-01-08 15:59:14-- http://10.1.6.28/test.jpg Connecting to 10.1.6.28:80... connected. HTTP request sent, awaiting response... HTTP/1.1 304 Not Modified Server: nginx/1.9.7 Date: Fri, 08 Jan 2016 07:59:14 GMT Last-Modified: Fri, 08 Jan 2016 07:25:26 GMT Connection: keep-alive ETag: "568f6466-4f51" Expires: Sat, 09 Jan 2016 07:59:14 GMT Cache-Control: max-age=86400 2016-01-08 15:59:14 ERROR 304: Not Modified.
·Expires:Sat,09 Jan 201607:47:28 GMT即服务器端通知客户端,在Sat,09 Jan 201607:47:28 GMT之前需要获取该资源时,不必再发起HTTP请求,直接使用这个缓存文件即可。
·Cache-Control:max-age=86400即服务器端通知客户端,你自收到这个文件起的86400秒内,都可以放心使用,不必再重复请求这个URL。
注意
和是对同一个意思的两种表示,前一个是绝对时间,后一个是相对时间。这两个指令同时使用时,max-age优先起作用,因为有时客户端和服务器端的时钟并不完全一致,有时甚至差别较大,故使用相对值更加合理。