HTTP协议之缓存

前言

上一篇文章HTTP 协议学习笔记主要分析了HTTP协议的一般请求原理,本文将着重分析,HTTP协议中的缓存

HTTP协议中定义了一些缓存控制相关的字段,属性,能够用来实现不同的缓存策略,但是注意,这些字段,属性,仅仅是HTTP协议中预先定义好的内容,具体怎么实现,还要我们的客户端,服务端,分别实现不同的逻辑才行

缓存相关字段

响应头

cache-control: 对应如下一些属性

1
2
3
4
5
6
public	所有内容都将被缓存(客户端和代理服务器都可缓存)
private 内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)
no-cache 必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证令牌 (ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载。
no-store 所有内容都不会被缓
must-revalidation/proxy-revalidation 如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证
max-age=xxx (xxx is numeric) 缓存的内容将在 xxx 秒后失效, 这个选项只在HTTP 1.1可用, 并如果和Last-Modified一起使用时, 优先级较高

举个例子,当客户端收到服务端响应,发现header 中有cache-control 字段,并且属性为 mas-age=10,即表示,这个接口的返回数据需要缓存,并且缓存内容在10秒后过期,那么客户端应该将接口数据保存起来,并记录保存的时间,下次请求的时候,对时间进行对比,如果缓存没有失效,那么就不再进行网络请求,直接返回缓存数据,如果缓存失效,那么重新请求网络数据

如果和Last-Modified一起使用时, 优先级较高

Last-Modified
表示请求的资源最后被修改的时间,对应的请求头中需要添加If-Modified-Since字段

1
Last-Modified: Mon, 26 Apr 2010 13:22:17 GMT

ETag

表示请求的资源的标识,这个标识可以是任意算法得到的,具体以服务端实现为准,一般来说,资源改变的话ETag就需要改变,这个字段需要对应请求头中的If-None-Match来使用

1
ETag: "92c027-897-4bd59389"

请求头

If-Modified-Since
在请求数据的时候询问服务端,我所请求的数据从If-Modified-Since 指定的日期开始,是否有修改,如果有修改,服务端返回200 然后返回全部数据,如果没有修改,返回304,客户端使用本地缓存

1
If-Modified-Since: Fri, 12 May 2006 18:53:33 GMT

If-None-Match: ETag
在请求数据的时候询问服务端,我所请求的数据的标识是否匹配 If-None-Match 指定的值,如果匹配,说明ETag没有改变,服务端返回304,客户端使用本地数据,否则服务端返回200,并返回全部数据

1
If-None-Match: W/"50b1c1d4f775c61:df3"

具体缓存逻辑

cache-control Only

第一次请求

当客户端第一次请求的时候,本地肯定没有缓存,此时服务端返回cache-control : max-age=1000,服务端告诉客户端,此次请求的内容需要被缓存,并且缓存在1000秒后失效,客户端收到响应后,解析响应头,发现存在cache-control : max-age=1000,将请求数据保存,key为接口url以及参数拼接成的字符串

第二次请求
客户端发出同样的请求,首先从本地查找是否存在缓存文件,发现缓存文件,检查是否在有效期内,如果在有效期内,直接返回缓存数据,不做网络请求,如果缓存已经失效,重新请求数据

cache-control+Last-Modified

第一次请求

当客户端第一次请求的时候,本地肯定没有缓存,此时服务端返回cache-control : max-age=1000,服务端告诉客户端,此次请求的内容需要被缓存,并且缓存在1000秒后失效
客户端收到响应后,解析响应头,发现存在cache-control : max-age=1000,将请求数据保存,key为接口url以及参数拼接成的字符串
发现存在Last-Modified: Mon, 26 Apr 2010 13:22:17 GMT,将Last-Modified 时间保存起来,key为接口url以及参数拼接成的字符串

第二次请求
客户端发出同样的请求,首先从本地查找是否存在缓存文件,发现缓存文件,检查是否在有效期内,如果在有效期内,直接返回缓存数据,不做网络请求

如果缓存已经失效,重新请求数据,由于对应的key 存在Last-Modified字段,所以请求的时候需要在请求头额外添加If-Modified-Since: Mon, 26 Apr 2010 13:22:17 GMT 向服务端询问,数据从If-Modified-Since 提供的日期开始是否修改过

服务端接到请求,检查数据是否修改过,如果修改过,返回200 并返回全部最新数据,如果没有修改过,返回304

客户端收到304继续使用本地缓存

cache-control+ETag

逻辑上与cache-control+Last-Modified是一样的,只不过 服务端返回的Last-Modified: Mon, 26 Apr 2010 13:22:17 GMT变成了ETag: "92c027-897-4bd59389"

客户端请求的If-Modified-Since: Mon, 26 Apr 2010 13:22:17 GMT变成了If-None-Match: W/"50b1c1d4f775c61:df3"

服务端缓存的字段中 cache-control的优先级最高

流程图

第一次请求

第二次请求