直白理解一文搞定http协议缓存
来源声明
本文来源如下文章,一些实验数据和结论也是基于该文章:
https://mp.weixin.qq.com/s/GkQNZRWIq6MxVE1PeASZkg
作者:vajoy
来源:https://www.cnblogs.com/vajoy/p/5341664.html
前言
由于http协议在缓存机制这一块做了很多次迭代。
并且每次迭代都做了向下兼容(因为如果你不向下兼容,一些顽固的古董的浏览器厂商不愿意升级就会没有支持http协议了。为了迁就他们所以做了向下兼容)
为了我们更好记住最新的,重要的,简单的,常用的缓存机制,我们先讲终点。然后再掘坟,考古。
一.最新的,重要的,简单的,常用的字段
cache-control 控制缓存读写
这个是http1.1的产物
小贴士
http协议有3个版本:
http1.0第一个版本,主要是完成简单的超文本传输
http1.1新增了拓展,缓存机制,绘画保持的长链接,新增状态码,host路由…
http2.0对性能优化,新增多路复用,优化http帧,压缩算…基本上就是优化传输性能,毕竟现在数据越来越大,不优化不行。
在http世界里面,浏览器本地和服务器都有各自的缓存机制,服务器和客户端都可以通过协商控制这两个缓存。
他们就是通过cache-control完成的。
他们可以通过这个指令,来实现,要不要读取缓存,读取多老旧的缓存,还是读取最新数据,也可以实现,要不要写入缓存(客户端和服务器的缓存)。
最常用的指令就是缓存禁用了,直接在请求头或者响应头声明, cache-control:no-store 即可 (no-store表示不写缓存,比较强势,no-cache表示不读取,没那么强势)
Http1.1版本的 if-match和if-none-match 配合 etag 实现缓存改动检验,从而优化缓存性能。
if-match和if-none-match 配合 etag 实现缓存改动检验,从而优化缓存性能。
因为很多时候,缓存时间过期了,并不意味着缓存数据被更新。
所以为了检测数据是否真的被更新。我们会对缓存生产一个类似md5摘要算法的校验码,这个校验码就是etag.
如果校验码一致,自然就不更新了,即使过期时间到了,也不更新缓存。
那为什么要搞 if-match和if-none-match 两个指令呢?
他们的区别主要是对状态码进行控制。
先说现象再说结论:
先说现象,读者自己细品。然后说结论,讲我的个人看法,
我们有了etag后,自然就只有两个结果,要么etag识别数据没改动,要么etag识别数据被改动过。
if-match :
改动了返回 200
没改动返回 304
if-none-match:
改动返回 412
没改动返回 200
个人理解:
if-match 侧重于尽可能的读取数据,不惜任何性能代价(就算要远程发起请求也要拿最新数据),不管成功还是没成功,而且越新越好,返回200表示数据是最新的版本。
if-none-match 侧重于性能优先,一定只读缓存,如果读不到就直接412,不读了,感觉这个功能有点鸡肋。
http1.0版本的 if-modified-since 和 if-unmodified-since 配合 last-modified (last-modified 是一个时间戳)
这个是旧版本的,功能跟 Http1.1版本的 if-match 是一个套路的。
唯一的区别是这个http1.0的机制依靠最近更新时间来检测是否被改动,这明显不靠谱,性能显然没有上面基于etag摘要算法那么好。
expire 是 http1.0的机制,其实就是缓存过期机制,这里不讲了。
结论:
大家好好理解 cache-control 和 if-match + etag 机制就好了。
并且记得,禁用缓存的最佳实践是 cache-control:no-store。
基本上就算ok了。