缓存
缓存是可以自动保存常见文档副本的HTTP设备。当Web请求抵达缓存时,如果本地已有“已缓存的”副本,就可以从本地存储设备而不是原始服务器中提取这个文档。 ##缓存的优点
- 缓存可以减少冗余的数据传输。
- 缓存可以缓解网络的瓶颈问题。
- 缓存在破坏瞬间拥塞(Flash Crowds)时非常重要:突发事件导致很多人几乎同时去访问一个Web文档时,就会出现瞬间拥塞,由此造成的过多流量峰值可能会使网络和Web服务器产生灾难性的崩溃。
- 减小距离时延:即使带宽不是问题,距离也可能成为问题。每台网络路由器都会增加网络流量的时延。将缓存放在客户端附近的机房里可以将文件传输距离从数千公里缩短至几公里甚至几百米。
缓存命中问题
用已有的副本为请求提供服务称为缓存命中。一些请求可能没有缓存副本称为缓存未命中,要转发给原始服务器。原始服务器内容可能会发生变化,缓存要时不时的对其进行检测以确定保存的副本是否最新,称为HTTP再验证(Revalidation)。
缓存可以在任意时刻,以任意的频率对副本进行再验证。HTTP提供了几个用来对已缓存对象进行再验证的工具,最常用的是If-Modified-Since首部。将这个首部添加到GET请求中去,就可以告诉服务器,只有在缓存了对象的副本之后,又对其进行了修改的情况下,才可以发送此对象。
- 文档命中率 说明阻止了多少通往外部网络的HTTP事务,提高文档命中率可以降低整体延迟。对现在中等规模的Web缓存来说,40%的命中率是很合理的。
- 字节命中率 说明阻止了多少字节传向因特网,提供字节命中率对节省带宽很有利。
客户端如何区分缓存命中与否?
HTTP没有为用户提供一种手段来区分响应是来自缓存还是来自原始服务器。
客户端可以使用Date首部,将响应中的Date首部的值与当前时间比较,如果响应中的日期值比较早,客户端通常可以认为这是一条缓存的响应。
缓存的拓扑结构
- 层次结构:父子缓存
- 网状缓存:内容路由
- 对等缓存 网状缓存中的代理缓存之间更加复杂:动态决定与哪个父缓存进行对话,或者决定绕开缓存直接与原始服务器进行对话。这种代理缓存会决定选择何种路由对内容进行访问、管理和传送,因此称为内容路由器。
缓存之间更为复杂的关系允许不同的组织互为对等体,将它们的缓存连接起来以实现共赢。提供可选的对等体的缓存称为兄弟缓存。
HTTP并不支持兄弟缓存。人们对HTTP进行了一定的扩展:
- Internet Cache Protocol
- HyperText Caching Protocol
缓存的处理步骤
对一条HTTP GET报文的基本缓存处理过程包括7个步骤:
接收
从网络中读取抵达的请求报文
解析
缓存对报文进行解析,提取出URL和各种首部
查找
查看是否有本地副本可用,如果没有,就从原始服务器获取一份副本并保存在本地 已缓存对象中包含了服务器响应主体和原始服务器响应首部,这样就会在缓存命中时返回正确的服务器首部。
新鲜度检测
查看已缓存副本是否足够新鲜,如果不是,就询问服务器是否有任何更新
创建响应
缓存的响应看起来就像来自原始服务器一样。
缓存将已缓存的服务器响应首部作为响应首部的起点,然后缓存对这些基础首部进行了修改和扩充。 比如HTTP版本;缓存还会向其中插入新鲜度信息(Cache-Control,Age以及Expires),而且通常会包含一个Via首部来说明请求是由一个代理缓存提供的。
缓存服务器不应该调整Date首部。 Date首部表示的是原始服务器最初产生这个对象的日期。
发送
将响应报文发往客户端
日志
记录本次请求日志
副本新鲜度检测
文档过期
通过特殊的HTTP Cache-Control首部和Expires首部,HTTP让原始服务器向每个文档附件了一个过期日期。
- Expires:绝对日期
- Cache-Control:相对时间(生存时间以秒为单位)
服务器再验证
缓存文档的过期了并不以为着它和原始服务器上的文档不一致,只是到了重新进行核对的时间了。这种情况称为服务器再验证。
- 如果再验证显示内容发生变化,缓存会获取一份新的文档副本,并将其存储在旧文档的位置上,然后将文档发送给客户端。
- 如果再验证显示内容没有变化,缓存只需要获取新的首部,包括一个新的过期日期,并对缓存中的首部进行更新就行了。
用条件方法进行再验证
HTTP允许缓存服务器向原始服务器发送一个条件GET,请求原始服务器只有在文档与缓存中现有的副本不同时,才回送对象主体。
HTTP定义了5个条件请求首部。对缓存再验证来说最有用的2个:
- If-Modified-Since:
如果从指定日期之后文档被修改过了,就执行请求的方法。可以与Last-Modified服务器响应首部配合使用。 - If-None-Match:
服务器可以为文档提供特殊的标记(ETag),而不是将其与最近修改日期匹配,这些标签就像序列号一样。
控制缓存的能力
服务器可以通过HTTP定义的几种方式来指定在文档过期之前可以将其缓存多长时间。
- Cache-Control: no-store
- Cache-Control: no-cache
- Cache-Control: must-revalidate
- Cache-Control: max-age
- Expires
客户端的新鲜度限制
Refresh按钮
Refresh会发布一个附加了Cache-Control请求首部的GET请求,这个请求会强制进行再验证,或者无条件地从服务器获取文档。
Refresh的确切行为取决于特定的浏览器、文档以及拦截缓存的配置。
Cache-Control: max-stale 缓存可以随意提供过期的文件
Cache-Control: max-stale=<s>
Cache-Control: min-fresh=<s>
Cache-Control: max-age=<s> 缓存不能返回缓存时间超过s秒的文档
Cache-Control: no-cache 除非资源进行了再验证,否则这个客户端不会接受已经缓存的资源
Cache-Control: no-store 缓存应该尽快从存储器中删除文档的所有痕迹
Cache-Control: only-if-cached 只有当缓存中有副本存在时,客户端才会获取一份副本