http缓存规则

web缓存可以自动保存常见文档副本,当web请求抵达缓存时,如果本地有已缓存的副本,就可以从本地存储设备而不是原始服务器中提取这个文档。使用缓存可以减少冗余的数据传输、缓解网络瓶颈问题、降低对原始服务器的要求和降低距离时延。

可以用已有的副本为某些到达缓存的请求提供服务,被称为缓存命中(cache hit),若请求没有副本可用,被转发给原始服务器,被称为缓存未命中(cache miss)。原始服务器的内容可能会发生变化,缓存要不时对其进行检测,被称为http再验证(revalidation)。

对缓存的副本进行再验证时,会向原始服务器发送一个小的再验证请求,如果内容没有变化,服务器会以一个小的304 Not Modified进行响应,副本依然有效,被再次标识为暂时新鲜的,并将副本提供给客户端,这被称为再验证命中或缓慢命中,这种方式比单纯的缓存命中要慢。

缓存处理步骤

对一条http GET报文的基本缓存处理包括7个步骤:
1、接收
缓存从网络中读取抵达的请求报文
2、解析
缓存对报文进行解析,提取出URL和各种首部
3、查询
查看是否有本地副本可用,如果没有,就获取一份副本,并将其保存在本地。
4、新鲜度检测
http通过缓存将服务器文档的副本保留一段时间,在这段时间里,都认为文档是新鲜的,缓存可以在不联系服务器的情况下直接提供该文档。但一旦已缓存副本停留时间太长,超过了文档的新鲜度限值,就认为对象过时了,在提供该文档之前,缓存要再次与服务器进行确认,以查看文档是否发生了变化。客户端发送给缓存的所有请求首部自身都可以强制缓存进行再验证,或者避免验证。
5、创建响应
缓存会用新的首部和已缓存的主体来构建一条响应报文。缓存会向其中插入新鲜度信息(Cache-Control、Age、Expires),并且通常会包含一个Via首部来说明请求是由一个代理缓存提供的。
6、发送
通过网络将响应发回给客户端
7、日志
可选地创建一个日志文件条目来描述这个事务

http有一些简单的机制可以在不要求服务器记住有哪些缓存拥有其文档副本的情况下保持已缓存数据与服务器数据之间充分一致。http将这些简单的机制称为文档过期和服务器再验证。

文档过期

通过http Cache-Control(http/1.1)和Expires(http/1.0+)首部,http让原始服务器向每个文档附加了一个过期日期,这些首部说明了在多长时间内可以将这些内容视为新鲜的。在缓存文档过期前,可以以任意频率使用这些副本,而无需与服务器联系,除非客户端请求中包含有阻止提供已缓存或未验证资源的首部。一旦已缓存文档过期,缓存就必须与服务器进行核对,询问文档是否被修改过,如果被修改过,就要获取一份新鲜的副本。由于绝对日期依赖于计算机时钟的正确设置,一般更倾向于使用Cache-Control相对日期。

Cache-Control:no-Store
标识为no-store的响应会禁止保存文档副本
Cache-Control:no-Cache
标识为no-cache的响应实际上时是可以存储本地缓存的,只是在与原始服务器进行新鲜度再验证之前,缓存不能提供给客户端使用
Cache-Control:must-revalidate
可以配置缓存,使其提供一些陈旧(过期)的对象,如果原始服务器希望严格遵守过期信息,可以增加must-revalidate首部

试探性过期

如果响应中没有Cache-Control:max-age首部,也没有Expires首部,缓存可以计算出一个试探性最大试用期。LM-Factor算法是一种常见试探性过期算法,如果文档中包含了最后修改日期,就可以使用这种算法。LM-Factor算法将最后修改日期作为依据,来估计文档有多易变。算法逻辑如下:
1、如果已缓存文档最后一次修改发生在很久以前,它可能是一份稳定的文档,不太会突然发生变化,因此将其继续保存正在缓存中比较安全
2、如果已缓存文档最近被修改过,说明它很可能会频繁地发生变化,因此在与服务器进行再验证之前,只应该将其缓存很短一段时间

实际的LM-Factor算法会计算缓存与服务器对话的时间跟服务器声明文档最后被修改的时间之间的差值,取这个间隔时间的一部分,将其作为缓存中的新鲜度持续时间。如果最后修改日期也没有的话,通常会为没有任何新鲜周期线索的文档分配一个默认的新鲜周期(一个小时或一天)。有时,比较保守的缓存会将这种试探性新鲜生存周期设置为0,强制在每次将其提供给客户端之前都去验证。

服务器再验证

缓存文档过期,意味着到了进行核对的时间,需要询问原始服务器文档是否发生了变化。这种情况被称为服务器再验证。如果在验证显示内容发生了变化,缓存会获取一份新的文档副本,取代旧的文档副本,然后将文档发送给客户端;如果再验证显示内容没有变化,缓存只需要获取新的首部,包括一个新的过期日期,并对缓存中的首部进行更新。

用条件方法进行再验证

http允许缓存向原始服务器发送一个“条件GET”,使服务器只有在文档与缓存中现有副本不同时,才回送对象主体,常用的两个首部是If-Modified-Since和If-None-Match。如果服务器收到的请求既带有If-Modified-Since又有If-None-Match,那么只有这两个条件都满足时,才返回304.

If-Modified-Since

If-Modified-Since再验证请求通常被称为IMS请求,可以与Last-Modified首部配合工作,参是数一个日期。如果自指定日期后,文档被修改了,Get请求就会成功执行,返回新的文档,新文档会包括一个新的过期日期。如果文档没有被修改,条件为假,客户端会收到一个304 Not Modified响应报文,一般会发送一个新的过期日期。

If-None-Match

有些情况仅使用最后修改日期再验证是不够的。

  • 有些文档可能会被周期性地重写,但实际包含的数据是一样的,尽管内容没有变化,但修改日期会发生变化
  • 有些文档可能被修改了,但所做修改并不重要,不需要让世界范围的缓存都重装数据(例如对拼写或注释的修改)
  • 有些服务器无法准确地判定文档的最后修改日期
  • 有些服务器提供的文档会在亚秒间隙发生变化,对这些服务器来说,以秒为粒度的修改日期就不够用了

为了解决这些问题,http允许用户对被称为实体标签(ETag)的“版本标识符”进行比较。实体标签是附加到文档上的任意标签,它们可能包含了文档的序列号或版本名,或者是文档内容的校验和其他指纹信息。当发布者对文档进行修改时,可以修改文档的实体标签来说明这个新的版本,缓存就可以用If-None-Match条件首部来请求文档的新副本了。

浏览器控制

浏览器中通常有refresh(刷新)和reload(重载)机制,可以强制对浏览器或代理缓存中可能过期的内容进行刷新。refresh操作会发布一个附加了Cache-Control请求首部的GET请求,这个请求会强制进行再验证,或者无条件地从服务器获取文档。refresh的确切行为取决于特定的浏览器、文档以及拦截缓存的配置。

Chrome中正常重新加载会强制对缓存的文档副本进行再验证,硬性重新加载则直接跳过缓存从原始服务器请求文档

你可能感兴趣的:(缓存,http)