HTTP缓存的工作原理和实现机制
HTTP缓存的工作原理
- 接收:读取请求报文
- 解析:对请求报文进行解析,提取URL和各种首部字段
- 查询:查看是否有本地缓存可用,如果没有,则从服务器获取并存储到本地
- 新鲜度(有效期)检查:缓存不会一直有效,是有过期时间的,在有效期之内才可以使用,否则需要向服务器查询对应资源是否有更新。
- 创建响应:缓存会用新的首部字段和缓存的响应主体来构建响应报文
- 发送:将相应发送给客户端
- 日志:缓存可以创建一条日志来记录这个HTTP事务
流程如下图所示:
HTTP缓存的实现机制
基于HTTP协议的HTTP缓存是通过在请求头和响应头中设置相应的字段值来实现的。
Expires
Expires
字段的值为服务器返回的缓存资源的到期时间(绝对时间),即下一次请求时间小于服务端返回的到期时间,直接使用缓存数据。
Expires
是HTTP/1.0的东西,现在浏览器默认使用HTTP/1.1,所以基本忽略。
Cache-Control
Cache-Control
字段可以设置多个属性值,常见属性及含义如下所示
no-store
:禁止进行缓存,缓存中不得存储任何客户端请求服务端响应的内容,每次客户端发起的请求都会从服务端下载完整的响应内容;no-cache
:强制确认缓存,每次请求发出时,缓存会将此请求发送到服务器,服务器会验证请求中所描述的缓存是否过期,若未过期,则缓存才使用本地缓存副本。public
:用于共享缓存,任何中间代理都可以缓存响应private
:用于私有缓存,只有客户端浏览器才可以缓存响应,没有指定public
时,默认为private
max-age
:用于设置缓存有效期,max-age
是距离请求发起时间的秒数,是一个相对值,如果响应头中存在Expires
和max-age
以max-age
为准。must-revalidate
使用该指令时,意味着缓存在考虑使用一个陈旧的资源时,必须先验证他的状态,已过期的缓存将不被使用,该属性与no-cache
的区别在于,使用no-cache
时,不管本地资源缓存副本是否过期,使用资源缓存副本前一定要到源服务器进行副本有效性校验,而must-revalidate
则不然,只有在本地资源缓存副本过期后,才去源服务器进行有效性检测。
Last-Modified/If-Modified-Since
Last-Modified
字段常用于响应头中,告知客户端资源的最后修改时间,这样当客户端再次请求该资源时,会在If-Modified-Since
请求字段中带上上次请求返回的最后修改时间,服务器收到请求报文后发现请求头包含If-Modified-Since
字段,则与请求资源的最后修改时间对比。如果资源的最后修改时间大于If-Modified-Since
字段值,说明资源又被修改过,则返回完整的资源内容,对应响应状态码为200
;如果资源的最后修改时间小于或等于If-Modified-Since
字段值,说明资源没有做新的修改,则返回状态码304
,告知浏览器使用本地保存的缓存作为响应实体。
Etag/If-None-Match
Etag
用于响应头中,告知客户端资源在服务器的唯一标识(生成规则有服务器指定,每当资源发生修改后Etag
值会变化),当客户端再次请求资源时,通过If-None-Match
字段通知服务器客户端缓存资源的唯一标识。服务器收到请求报文发现请求头中包含If-None-Match
字段,则与被请求资源的唯一标识作对比,如果不同则说明资源被改动过,则返回资源的完成内容,状态码为200
;如果相同说明资源没有修改,返回状态码304
,告知浏览器使用本地保存的缓存作为响应实体。
Etag
/If-None-Match
的优先级要高于 Last-Modified
/If-Modified-Since
,如果同时出现,以前者为准。