HTTP中的强缓存与协商缓存 - 掘金 (juejin.cn)
缓存:浏览器缓存、DNS缓存和CDN缓存_Qssn丶的博客-CSDN博客_浏览器缓存和dns缓存
从输入URL开始建立前端知识体系 - 掘金 (juejin.cn)
我们都知道当我们在浏览器中打开一个页面时,浏览器会根据你输入的URL到对应的服务器上请求你想要的数据资源。但这个过程中可能页面可能需要等待一段时间(白屏时间)才能渲染到你的页面中。
当你想要提高用户体验时,那就不得不提各种缓存技术了,例如:DNS缓存、CDN缓存。浏览器缓存、页面本地缓存等等,有一个良好的缓存策略可以减低重复资源的请求,降低服务器的开销,提高用户页面的加载速度。
介绍各种各样的缓存策略,因为都是规范相关的内容,于是就看了多篇文章各取优点进行一个整理(缝合一下,再夹带一点私活)
浏览器缓存
浏览器缓存分为强缓存和协商缓存,当我们输入URL时,浏览器首先会解析出协议、主机、端口、路径等信息,并构造一个 HTTP 请求,在发送http请求之前会先判断一下是否有缓存。浏览器缓存是建立在重复请求的前提下的,简单概述一下浏览器缓存的流程
浏览器再次发送请求时:
- 首先判断强缓存,强缓存生效直接使用强缓存(200 from memory、from disk 先从内存,再从硬盘),如果强缓存不生效就换采用协商缓存策略
- 没有设置协商缓存就直接重新请求(200)
- 设置了协商缓存则由服务器判断缓存是否失效,没有失效就继续使用缓存(304,同强缓存的获取方式),失效则返回新的文件(200)
另一种说法:
-
浏览器发送请求前,根据请求头的
expires
和cache-control
判断是否命中(包括是否过期)强缓存策略,如果命中,直接从缓存获取资源,并不会发送请求。如果没有命中,则进入下一步。 -
没有命中强缓存规则,浏览器会发送请求,根据请求头的
If-Modified-Since
和If-None-Match
判断是否命中协商缓存,如果命中,直接从缓存获取资源。如果没有命中,则进入下一步。 -
如果前两步都没有命中,则直接从服务端获取资源。
强缓存
强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。强缓存又分为两种Expires
和Cache-Control
expires
- 版本:HTTP/1.0
- 来源:存在于服务端返回的响应头中
- 语法:Expires: Wed, 22 Nov 2019 08:41:00 GMT
- 缺点:服务器的时间和浏览器的时间可能并不一致导致失效
Expires
是http1.0
的规范,用于表示资源的过期时间的请求头字段,值是一个绝对时间,是由服务器端返回的。
在浏览器第一个请求资源时,服务器端的响应头会附上Expires
这个响应字段,当浏览器在下一次请求这个资源时会根据上次的expires
字段是否使用缓存资源(当请求时间小于服务端返回的到期时间,直接使用缓存数据)
expires是根据本地时间来判断的,假设客户端和服务器时间不同,会导致缓存命中误差
Cache-Control
- 版本:HTTP/1.1
- 来源:响应头和请求头
- 语法:Cache-Control:max-age=3600
- 缺点:时间最终还是会失效
expires在客户端本地时间和服务器时间不一致时会产生误差,因此在http1.1中提出了Cache-Control,它设置了一个字段max-age是从当前时间开始计时,在该时间内不与服务器重新请求新的数据,是优于expires的,因此在同时启用的时候它的优先级高于expires
协商缓存
协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程
1.当浏览器发起一个资源请求时,浏览器会先判断本地是否有缓存记录,如果没有会向浏览器请求新的资源。
2.如果有缓存记录,先判断强缓存是否存在(cache-control
优先于expires
,后面会说),如果强缓存的时间没有过期则返回本地缓存资源(状态码为200)
3.如果强缓存失效了,客户端会发起请求进行协商缓存策略,首先服务器判断Etag
标识符,如果客户端传来标识符和当前服务器上的标识符是一致的,则返回状态码 304 not modified
(不会返回资源内容)
判断过程如下:
- 浏览器请求资源,服务器返回报文中加入Etag值,资源更新则Etag值也会更新。
- 浏览器再次请求资源,此时请求报文会加入If-None-Match,值为上一次响应报文的Etag值。
- 服务器比对报文的If-None-Match和当前的Etag是否一致,不一致则更新Etag并且返回,下一次浏览器请求Etag将传输新的值。如果一致表示资源没有更新,状态码返回304,浏览器从本地缓存获取,此时响应头会同时返回Etag值。(虽然没有变化)
4.如果没有Etag
字段,则比对Last-Modified。
- 浏览器第一次向服务端请求之后,服务端响应中加入Last-Modified 字段,表示资源最后一次修改时间。
- 浏览器再次请求,在请求报文中会加入If-Modified-Since 字段,字段值等于上一次浏览器返回的Last-Modified (最后一次修改时间)。
- 服务器比对Last-Modified 和If-Modified-Since 字段,如果不一致则接受资源并且返回更新之后的资源,如果一致表示资源没有更新,返回304状态码,此时浏览器会从本地缓存获取资源文件。值得注意的是,本地请求如果是304,此时响应头中不会再添加Last-Modified字段。
5.如果Etag
和服务器端上的不一致,重新获取新的资源,并进行协商缓存返回数据。
状态码区别
- 200 请求成功,服务器返回全新的数据
- 200
from memory cache / from disk cache
本地强缓存还在有效期,直接使用本地缓存 - 304 请求成功,走了协商缓存,服务器判定(
Etag
和Last-modified
)没有过期,告知浏览器使用缓存
用户行为对缓存的影响
- 当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存。
- 当f5刷新网页时,跳过强缓存,但是会检查协商缓存。
- 浏览器地址栏中写入URL,回车 浏览器发现缓存中有这个文件了,不用继续请求了,直接去缓存拿。
缓存的位置
service worker
Service Worker
是运行在浏览器背后的独立线程,一般可以用来实现缓存功能,使用 Service Worker
的话,传输协议必须为 HTTPS
。因为 Service Worker
中涉及到请求拦截,所以必须使用 HTTPS
协议来保障安全。Service Worker
的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。
Memory Cache
Memory Cache
也就是内存中的缓存,主要包含的是当前中页面中已经抓取到的资源,例如页面上已经下载的样式、脚本、图片等。读取内存中的数据肯定比磁盘快,内存缓存虽然读取高效,可是缓存持续性很短,会随着进程的释放而释放。 一旦我们关闭Tab页面,内存中的缓存也就被释放了
Disk Cache
Disk Cache
也就是存储在硬盘中的缓存,读取速度慢点,但是什么都能存储到磁盘中,比之 Memory Cache
胜在容量和存储时效性上。
Push Cache
Push Cache
(推送缓存)是 HTTP/2
中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。
DNS缓存
有DNS的地方,就有缓存。浏览器、操作系统、Local DNS、根域名服务器,它们都会对DNS结果做一定程度的缓存:
- 首先查找浏览器自身的缓存
- 然后是本机hosts,如果还是没有,则查找本地DNS服务器
- 本地DNS服务器一般是动态分配的或者我们自己指定的地址(当然这里还有个路由器的缓存)
- 再查找不到,则向根服务器发送递归查找,边缘DNS > 顶级DNS > 二级DNS > 三级DNS(也就是网站注册的)
CDN缓存
在浏览器本地缓存失效后,浏览器会向CDN边缘节点发起请求。类似浏览器缓存,CDN边缘节点也存在着一套缓存机制。CDN边缘节点缓存策略因服务商不同而不同,但一般都会遵循http标准协议,通过http响应头中的Cache-control判断资源是否过期
其优势是:
1.CDN节点解决了跨运营商和跨地域访问的问题,访问延时大大降低。
2.大部分请求在CDN边缘节点完成,CDN起到了分流作用,减轻了源服务器的负载。
如果这篇文章对你有帮助,可以bilibili关注一波 ~ !此外,如果你觉得本人的文章侵犯了你的著作权,请联系我删除~谢谢!