摘要
🤔 1.缓存的优势
🤔 2.强缓存和协商缓存
🤔 3.不同浏览器下对缓存的策略不同
🤔 4.覆盖式发布和非覆盖式发布
🤔 5.覆盖式发布痛点
🤔 6.非覆盖式发布真的完美了吗?
缓存的优势
1.缓解资源服务器压力,减少网络带宽消耗
🤗:日均1000万PV的页面(页面有10个静态资源),假设其中有200万PV是属于已被缓存资源的用户发出的。那么对资源服务器来说,将减少200万*10 = 2000万次请求。
2.提升用户体验
🤗:用户下次访问页面时,无需发起资源的网络请求,将直接从浏览器缓存中读取缓存资源,响应更快。
总结
🤗:你好,我也好
强缓存和协商缓存
强缓存:
- 强缓存是利用http头中的
Expires
和Cache-Control
两个字段来控制的,用来表示资源的缓存时间 Expires
和Cache-Control
可以在服务端配置同时启用,同时启用的时候Cache-Control
优先级高
Expires
是http1.0的规范,它的值是一个绝对时间的GMT格式的时间字符串。例如:
expires:Sun, 08 Nov 2020 14:00:33 GMT
这个时间代表这这个资源的失效时间,只要发送请求时间是在Expires
之前,那么本地缓存始终有效,则在缓存中读取数据。所以这种方式有一个明显的缺点,由于失效的时间是一个绝对时间,所以「当服务器与客户端时间偏差较大时,就会导致缓存混乱」。
Cache-Control
已知Expires
的缺点之后,在HTTP/1.1中,增加了一个字段Cache-Control
,该字段表示资源缓存的最大有效时间,在该时间内,客户端不需要向服务器发送请求。例如:
Cache-Control:max-age=3600 // 代表着资源的有效期是3600秒
除了该字段还有其他的几个常用的值。
no-cache
:虽然字面意思是“不要缓存”,但实际上还是要求客户端缓存内容的,只是是否使用这个内容由后续的对比来决定。no-store
: 真正意义上的“不要缓存”。所有内容都不走缓存,包括强制和对比。public
:所有的内容都可以被缓存 (包括客户端和代理服务器, 如 CDN)private
:所有的内容只有客户端才可以缓存,代理服务器不能缓存。默认值。
协商缓存
- 「协商缓存命中后返回状态码304」
- **Cache-Control:max-age=0 或者 **「Cache-Control:no-cache 都会触发协商缓存」
- 「Etag优先级高于Last-Modified」
Last-Modified & If-Modified-Since
- 服务器通过
Last-Modified
字段告知客户端,资源最后一次被修改的时间,例如
Last-Modified: Mon, 10 Nov 2018 09:10:11 GMT
复制代码
- 浏览器将这个值和内容一起记录在缓存数据库中。
- 下一次请求相同资源时时,浏览器从自己的缓存中找出“不确定是否过期的”缓存。因此在请求头中将上次的
Last-Modified
的值写入到请求头的If-Modified-Since
字段 - 服务器会将
If-Modified-Since
的值与Last-Modified
字段进行对比。如果相等,则表示未修改,响应 304;反之,则表示修改了,响应 200 状态码,并返回数据。
但是他还是有一定缺陷的:
- 如果资源更新的速度是秒以下单位,那么该缓存是不能被使用的,因为它的时间单位最低是秒。
- 如果文件是通过服务器动态生成的,那么该方法的更新时间永远是生成的时间,尽管文件可能没有变化,所以起不到缓存的作用。
Etag & If-None-Match
为了解决上述问题,出现了一组新的字段 Etag
和 If-None-Match
Etag
存储的是文件的特殊标识(一般都是 hash 生成的),服务器存储着文件的 Etag
字段。之后的流程和 Last-Modified
一致,只是 Last-Modified
字段和它所表示的更新时间改变成了 Etag
字段和它所表示的文件 hash,把 If-Modified-Since
变成了 If-None-Match
。服务器同样进行比较,命中返回 304, 不命中返回新资源和 200。**
不同浏览器下对缓存的策略不同
覆盖式发布和非覆盖式发布**
「alt="image.png" style="max-width: 100%; border-radius: 6px; display: block; margin: 20px auto; object-fit: contain;">」 alt="image.png" style="max-width: 100%; border-radius: 6px; display: block; margin: 20px auto; object-fit: contain;">
覆盖式发布痛点
**场景:现代互联网企业,为了进一步提升网站性能,会把静态资源和动态网页分集群部署,静态资源将会被部署到CDN节点上。「「也就是说我们的html页面和静态资源需要分开部署。」」 **
1.先部署页面,再部署资源
在二者部署的时间间隔内,如果有用户访问页面,就会在新的页面结构中加载旧的资源,并且把这个旧版本的资源当做新版本缓存起来,其结果就是:用户访问到了一个样式错乱的页面,除非手动刷新,否则在资源缓存过期之前,页面会一直执行错误。
2.先部署资源,再部署页面
在部署时间间隔之内,有旧版本资源本地缓存的用户访问网站,由于请求的页面是旧版本的,资源引用没有改变,浏览器将直接使用本地缓存,这种情况下页面展现正常;但没有本地缓存或者缓存过期的用户访问网站,就会出现旧版本页面加载新版本资源的情况,导致页面执行错误,但当页面完成部署,这部分用户再次访问页面又会恢复正常了
非覆盖式发布真的完美了吗?
「随着项目的版本迭代,资源服务器下的资源也将越来越多salt="image.png" style="max-width: 100%; border-radius: 6px; display: block; margin: 20px auto; object-fit: contain;">」 每个项目下都存放着无数个版本的静态资源文件,这将直接导致:
1.提高了后续服务器迁移难度
2.服务器资源的浪费
「🙄 Answer: 所以我们应该尽可能的去删除那些已经用不到的文件」
「🤔 Question: 是的,但是我们的删除策略是什么?」