一、概述
分为两类:强制缓存和对比缓存
强制缓存:
只要本地有缓存并且对比时间没过期之前就可以继续使用,不用发起网络请求
对比缓存:
不管本地有没有缓存都要发起请求(通过if-none-match+if-modified-since携带上一次请求服务端返回的etag和last-modified参数值), 对比成功的话就返回状态304和header,不携带body,对比失败的话证明数据失效, 需要返回200以及完整数据以及新的缓存控制标志(cache-control+last-modified+etag)
强缓存直接减少请求数,是提升性能最大的缓存策略。在使用缓存优化网页性能时强,优先考虑强制缓存。
二、整体流程
**1)**第一次客户端请求携带cache-control参数,
**2)**服务端响应状态码200并返回数据(包括响应头的Cache-control+last-modified+etag),
**3)**客户端存储这些状态码和标志
**4)**第二次发起请求流程如下:
概述:
先检查是强制缓存还是对比缓存,决定是否需要再次发起请求, 如果是对比缓存就通过if-none-match+if-modified-since分别携带上一次请求服务端返回的etag+last-modified
细节:(基于客户端okhttp框架缓存源码)
.从lruDiscCache根据request拿到上次的response,如果response为空,就直接发起请求
.如果是https需要handshake握手信息
.检测本次request和上次响应的response是否设置了cache-control:no-store表明不使用任何缓存
.检测本次request是否设置了cache-control:no-cache表明不使用本地缓存,直接发起请求
.检查本次request是否有直接设置If-Modified-Since或者If-None-Match,如果已设置就直接发起请求
.检查max-age是否过期,没过期就直接使用上次相应的response
.将上次response的etag和last-modified-since设置给本次request,直接发起请求
**5)**服务端通过对资源的对比后决定该客户端是否需要更新缓存数据 如果需要,就返回200和完整数据包 如果不需要,就返回304以及响应头,不返回数据包,客户端接收到响应后就知道缓存是否可以重用
三、强制缓存
是否可用由客户端判断
expires(http1.0)
用于设定到期时间,时间是绝对时间(当前时间+缓存时间)
由服务器响应消息携带,告诉浏览器在过期之前不要请求
缺点:
1)绝对时间导致很容易通过修改客户端时间导致缓存时间判断失效
2)客户端时间可能和服务端时间不一致
3)写法复杂,时间格式要求比较严格
自从 HTTP/1.1 开始,Expires 逐渐被 cache-control 取代
cache-control(http1.1)
控制缓存类型或者缓存有效时间(这个header属性在请求头和响应头中都有),是一个相对时间
可选属性有
cache-control: public 服务和客户端都可缓存 (包括客户端和代理服务器, 如 CDN)
cache-control: private 只有客户端可以缓存,代理服务器不能缓存。是默认值
cache-control: no-store 对比缓存和强制缓存都不可用//直接发起请求
cache-control: no-cache 不使用强制缓存,需要使用对比缓存决定缓存是否可用
cache-control: max-age 返回给客户端资源最大有效时间,是一个相对时间,多少时间后失效
cache-control: must-revalidate: 如果 max-age 过期,浏览器必须向服务器发请求,验证资源是否还有效。 cache-control: only-if-cached :只从缓存中取,此时如果上次请求的结果为null那么就直接返回null了,请求失败
格式可拼接 ,例如可以Cache-Control:public, only-if-cached, max-stale=2419200
//强制缓存和对比缓存需要的数据都在这个Header里,对比缓存的etag和last-modified有单独的header标识
四、对比缓存(协商缓存)
由服务端判断,当强制缓存失效(超过规定时间)时,就需要使用对比缓存,由服务器决定缓存内容是否失效。
具体流程
1) 浏览器先请求 缓存数据库,返回一个 缓存标识(包括etag+last-modified)
2) 浏览器再次请求就拿这个 标识(if-none-match+if-modidied-since) 和服务器通讯
3) 如果缓存未失效,服务器返回 HTTP状态码304 表示继续使用,于是客户端继续使用缓存,如果缓存失效,服务器返回 HTTP状态码200 和新的数据及缓存规则,浏览器响应数据后,再把规则写入到缓存数据库,协商缓存在请求数上和没有缓存是一致的,但如果是 304 的话,返回的仅仅是一个状态码而已,并没有实际的文件内容,因此 在"响应体体积"上的节省是协商缓存的优化点。它的优化覆盖是的"响应时间"。通过减少响应体体积,来缩短网络传输时间。
两对控制缓存字段
服务响应 etag:唯一标志 客户请求 if-none-match:+唯一标志
服务响应 last-modified:时间 客户请求 if-modified-since:+时间
etag优先级更高,比较更准确,毫秒级
Last-Modified && If-Modified-Since 存在的一定缺陷:
1)如果资源更新速度是秒以下单位,那么该缓存不能被使用,因为它的时间单位最低是秒。
2)如果文件是通过服务器动态生成的,那么该方法的更新时间永远是生成的时间,尽管文件可能没有变化,所以起不到缓存的作用。
etag+if-none-match 可以解决上诉存在的问题,通过对文件取hash标识文件是否更改