Http缓存机制

真是一个庞大的话题

// HttpResponse
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT -->请求返回的最新时间
// (这个时间居然是服务器返回的,那如果发生服务器在Date+maxAge时间之前Response更新了怎么办?) 
Cache-Control: max-age=604800 --> 自Date时间开始,往后的max-age时间内可以认为这个Response是最新的
// 当client在Date+maxAge之前向Server发送了请求,当请求到了缓存服务器的时候,会回送这个字段,
// 代表当前时间-Date=Age < maxAge,因此Response是新鲜的
Age: 86400
// 这是一个过时的字段,在HTTP1.0中使用。表示Response应该在expires指示的时间之后过期
// 在HTTP1.1以后不再使用这个时间段的原因是:时间的格式比较难解析,并且时间可以通过修改系统时间来改变,不安全
// 当maxAge与expires字段同时存在,优先使用max-age字段
Expires: Tue, 28 Feb 2022 22:22:22 GMT

Http验证机制

通过前面的Http缓存机制,可以判断出当前响应在缓存服务中是新鲜的(fresh)还是过期的/陈旧的(stale)。

当Response被判断成是stale的时候,这时候应该采取另一种措施:向server重新发送请求来验证当前Response是否还是新鲜的。

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2022 22:22:22 GMT // 返回响应时间
// 当Request中包含if-modified-since字段,如果Response没有更新,会返回304和LAST-MODIFIED
Last-Modified: Tue, 22 Feb 2022 22:00:00 GMT 
Cache-Control: max-age=3600
// 服务端对Response计算之后得到的一个特定值
ETag: "deadbeef"

if-modified-since

If-Modified-Since 是一个条件式请求首部,服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为 200 。如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的 304 响应,而在 Last-Modified 首部中会带有上次修改时间。 不同于 If-Unmodified-Since, 

If-Modified-Since 只可以用在 GET 或 HEAD 请求中。

If-Modified-Since: , :: GMT If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT

即if-modified-since是client向server发送请求,并且带上时间,代表是否在该时间之前Response未改变过。

ETag / If-None-Match

使用Last-Modified返回上次修改时间,依然会有时间格式解析的问题,因此使用ETag来判断文档是否过期

ETag是server对Response进行某种算法,得到的一个值(比如是hash值)。

当Response过期之后,缓存服务器向Request加入上次Response得到的ETag值,如果服务器比对过ETag与最新Response的Etag没有变化,则返回304-NOT-MODIFIED。

client发送的请求,if-None-Match中塞入的是Response获取的Etag。

// client发 If-None-Match: "deadbeef"

当Etag和LAST-MODIFIED同时返回,以ETag优先。

禁止使用缓存、强制刷新

关于为什么缓存机制都是由服务器返回的Response来控制

If-Modified-Since: ,    :: GMT
If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT
  1. maxAge=0

maxAge=0,也代表所有Response都是过期的,因此都会去向服务器请求Response。no-cache是最新提出的方案。

maxAge=0只会每次请求前先去询问服务器Response是否过期,如果没过期,就返回304。过期了,就返回Response。

  1. no-cache

表示不使用缓存服务器,则可以确保Response是从服务器返回的。

这个参数一般会在用户强制下拉刷新的时候使用。

之前也有过一个问题,如果有maxAge的话,很可能会导致在maxAge期间,即使服务器有更新,也无法通知到客户端。这时候有一个方法就是,用户下拉刷新的时候,加入cache-control:no-cache,强制从服务器获取最新的Response。

  1. must-revalidate

max-age = 0一般与max-revalidate配合使用,达到no-cache的效果。

  1. no-store

不希望将Response存储在其他任何地方。跟no-cache的区别是,no-cache仍然有可能缓存Response,只不过会每次都去请求最新的。no-store也可以保证Response是最新的。

cache-control:private

共享缓存主要位于源服务器之前,旨在减少到源服务器的流量。

因此,如果多个相同的请求同时到达共享缓存,中间缓存将代表自己将单个请求转发到源,然后源可以将结果重用于所有客户端。这称为请求折叠。

当请求同时到达时会发生请求折叠,因此即使响应中给出了 max-age=0 或 no-cache,它也会被重用。

如果响应是针对特定用户个性化的,并且你不希望它在折叠中共享,则应添加 private 指令

Http缓存机制_第1张图片

启发式缓存

当没有给出cache-control字段时,一般会使用启发式缓存。

HTTP 旨在尽可能多地缓存,因此即使没有给出 Cache-Control,如果满足某些条件,响应也会被存储和重用。这称为启发式缓存。

例如,采取以下响应。此回复最后一次更新是在 1 年前。

HTTP/1.1 200 OK Content-Type: text/html Content-Length: 1024 Date: Tue, 22 Feb 2022 22:22:22 GMT Last-Modified: Tue, 22 Feb 2021 22:22:22 GMT …

试探性地知道,整整一年没有更新的内容在那之后的一段时间内不会更新。因此,客户端存储此响应(尽管缺少 max-age)并重用它一段时间。复用多长时间取决于实现,但规范建议存储后大约 10%(在本例中为 0.1 年)的时间。

启发式缓存是在 Cache-Control 被广泛采用之前出现的一种解决方法,基本上所有响应都应明确指定 Cache-Control 标头。

 

你可能感兴趣的:(http,缓存,网络协议)