缓存
Web缓存用于自动保存常见的文档。当HTTP请求到达时,如果本地有“已缓存的”副本,就可以从本地存储设备而不是原始服务器中提取文档。使用缓存有以下好处:
- 减少了冗余数据的传输,如重复传输同一份文档是没必要的,完全可以缓存到本地来减少冗余数据。
- 缓解了网络瓶颈,如:客户端会以路径最慢的网速访问服务器,如果客户端从一个快速局域网缓存中得到一份副本,那么缓存就可以提高性能。
- 缓存降低了对原始服务器的要求,如在大量请求访问服务器,会造成服务器过载,此时如果在整个路径的不同节点存在缓存,那么可以缓解阻塞,降低服务器要求。
- 缓存降低了距离时延,如两地具体极远,此时互相访问势必造成距离时延,如果在某一地附近机房有缓存,那么就可以大大降低距离时延。
缓存的命中和未命中
可以用已有的缓存副本为某些到达缓存的请求提供服务,这就被称为缓存命中;而到达的请求可能因为未缓存或缓存失效,导致请求到达了原始服务器,这就被称为缓存未命中。
再验证
原始服务器的内容可能会发生变化,缓存要时不时对其进行检车,看看保存的在本地的副本是否是最新的,避免缓存失效。这种“新鲜度检测”称为HTTP再验证。为了有效地进行再验证,HTTP定义了一些特殊的请求,不用从服务器获取整个文档,就可以快速的检测内容是否是最新的。
缓存进行再验证时,会向原始服务器发送一个小的再验证请求。如果内容没发生变化,服务器会以一小个的304 Not Modified进行响应。只要缓存指导副本仍然有效,就会再次标记副本为暂时新鲜的,并将副本提供给客户端。这又被称为再验证命中。
服务器接收到GET If-Modified-Since请求时可能发生的情况:
再验证命中
如果服务器对象未被修改,服务器会向客户福安发送一个小的304 Not Modified响应。
再验证未命中
如果服务器对象与已缓存的副本不同,服务器会向客户端发送一条普通的、带有完整内容的HTTP 200 OK响应
对象被删除
如果服务器对象被删除,此时服务器就返回404响应,缓存收到404响应后会同步把本地缓存副本也一并删除。
区分命中和未命中的情况
HTTP实际上并未提供一种手段来区分响应是缓存命中的,还是访问原始服务器得到的。客户端有一种方法可以判断响应是否来自缓存,就是使用Date首部。将响应中Date首部的值与当前时间进行比较,如果响应中的日期比较早,客户端通常可以认为这是一个缓存响应,客户端也可以通过Age首部来检测缓存的响应,通过这个首部可以分辨出这条响应的使用期。
缓存的处理步骤
对一条HTTP GET报文的缓存处理基本包括7步:
- 接收:缓存从网络中读取抵达请求报文。
- 解析:缓存对报文进行解析,提取出URL和各种首部
- 查询:缓存查看是否有本地副本可用,如果没有,就获取一份副本并保存到本地
- 新鲜度检测:缓存查看已缓存副本是否足够新鲜,如果不是,就询问服务器是否有任何更新
- 创建响应:缓存会用心的首部和已缓存的主题来构建一条响应报文
- 发送:缓存通过网络将响应发送给客户端
- 日期:缓存可选地创建一个日志文件条目来描述此次事务。
保持副本的新鲜
由于服务器文档可能每时每刻都在变化,因此需要保持缓存副本是最新的。HTTP使用简单的机制可以不要求服务器记住有哪些缓存拥有其文档副本的情况下,保持已缓存的数据与服务器数据之间保持一致。这种简单的机制有2种,一种是前文提到的再验证,还有一种就是文档过期。
文档过期
通过特殊的HTTP首部Cache-Control和Expires,HTTP让原始服务器向每个文档加了一个“过期日期”。这些首部说明在多长时间内容可以将这些内容视为最新的。在缓存文档过期之前,缓存可以以任意频率使用这些副本,而无需与服务器联系,当然,除非客户端请求中包含有阻止提供已缓存或未验证资源的首部。但一旦缓存文档过期,缓存就必须与服务器进行核对,询问文档是否被修改过,如果是,则必须获取一份新鲜的文档。
过期日期和使用期
服务器使用HTTP/1.0+的Expires首部或HTTP/1.1的Cache -Ccontrol: max-age 响应首部来指定过期日期,同时还会带有响应主体。Expires首部和cache -Control:max-age首部所做的事情本质上是一样的,但由于Cache-Control首部使用的是相对时间而不是绝对日期,所以我们更倾向于使用比较新的Cache-Control首部。绝对日期依赖于计算机时钟的正确设置。
首部 | 描述 |
---|---|
Cache -Control :max-age | max-age 值定义了文档的最大使用期,从第一次生成文档到文档不再新鲜,无法使用为止,最大的合法生存时间(以秒为单位) Cache-Control: max-age-484200 |
Expires | 指定一个绝对的过期日期。如果过期日期已经过了,就说明文档不再新鲜了。Expires: Fri, 19 Jan 2020, 14:00:00 GMT |
用条件方法进行再验证
HTTP的条件方法可以高效地实现再验证。HTTP 允许缓存向原始服务器将发送一个“一条件GET”,请求服务器只有在文档与缓存中现有的副本不同时,才回送对象主体。通过这种方式,将新鲜度检测和对象获取结合成了单个条件GET。向GET求报文中添加一些特殊的条件首部,就可以发起条件GET。只有条件为真时,Web服务器才会返回对象。
HTTP定义了5个条件请求首部。对缓存再验证来说最有用的2个首部是If-Modified-since和If-None-Match。”所有的条件首部都以前缀“IF” 开头。
控制缓存的能力
服务器可以通过HTTP定义的几种方式来指定在文档过期之前可以将其缓存多长时间。按照优先级递减的顺序,服务器可以:
- 附加一个Cache-Control:no-store首部到响应中去
- 附加一个Cache-Control:no-cache首部到响应中去
- 附加一个Cache-Control:must-revalidate首部到响应中去
- 附加一个Cache-Control:max-age首部到响应中去 - 附加一个Expires日期首部到响应中去,
不附加过期信息,让缓存确定自己的过期日期。