浏览器HTTP缓存机制
说来惭愧,作为一名前端开发,只知道http缓存机制的存在,它可以优化http性能,但是http缓存到底是个啥,它是怎么工作的,那就不知道了
通常来说,我们在浏览器中打开一个页面,需要向服务器发送请求,请求css,图片,js等动态资源,这些静态资源修改的少,一般客户端会把它们存储起来,当客户端再次请求时,可以从本地缓存中直接读取,这样可以减少http请求,给服务器减负,
http缓存的优势就体现出来啦!Http 缓存机制作为 web 性能优化的重要手段,要想了解Http 缓存机制,得先弄清楚http的传输
一.http的传输
HTTP想要发送一条报文的时候,需要经过以下两个步骤:
- TCP三次握手建立起连接管道,HTTP报文会以流的形式通过该管道按顺序传输;
- TCP会将这些数据分别切割成数据块,并且封装在IP分组中,通过IP去传输;
使用TCP作为传输层:
- 传输可靠
- 有序
一个HTTP请求过程如下图所示:
针对以上图示,我们解答几个常见的问题:
a. 浏览器在发起请求时首先会做什么?答,查找本地缓存
根据URL查找本地缓存啦!先看本地缓存中是否有当前请求的URL的内容,如果存在,当然好了,直接用就好了。如果不存在,那就得去向服务器请求该URL了。
首先让我们回顾一下浏览器的缓存标识字段都有哪些:
Cache-control,指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。
Expires,Web服务器响应消息头字段,在响应http请求时告诉浏览器在过期时间前浏览器可以直接从浏览器缓存取数据,而无需再次请求。Expires是HTTP1.0的东西,所以它的作用我们可以基本忽略了。
Last-Modified,标示请求资源的最后修改时间。
Etag,web服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识。
这么多缓存标识,判断时肯定得有个优先级吧,那是肯定的,Cache-control优先级高于Expires,Etag优先级高于Last-Modified。说这么多,直接上图吧,看下图更清晰:
b. 浏览器查找完缓存之后接下来要做的是什么呢?答,DNS query
首先客户机将域名查询请求发送到本地DNS服务器,本地DNS服务器先在之前的记录(缓存)中查找,如果有缓存,则直接利用缓存进行解析,如果没有缓存,则进入本地的缓存的寻找。如果本地服务器不能在本地找到缓存,则将请求发送到根域名DNS服务器。
DNS服务器在拿到我们的域名后,会将它解析成IP地址返回给浏览器,这样浏览器就能直接定位到要请求的服务器的地址了。
c. 找到服务器地址之后肯定就是向服务器发送请求,建立连接,这个不用问了。
这样根据IP和端口,浏览器就开始跟服务器建立TCP连接啦。看到TCP连接,我们就想到了三次握手。
TCP是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在TCP/IP协议中,TCP协议提供可靠的连接服务,连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方的序列号和确认号并交换 TCP窗口大小信息。
第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器的确认;
第二次握手:服务器收到SYN报文段。服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,设置Acknowledgment Number为x+1(Sequence Number+1);同时,自己自己还要发送SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放到一个报文段(即SYN+ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK报文段。然后将Acknowledgment Number设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。
完成了三次握手,客户端和服务器端就可以开始传送数据。
d. 浏览器在接收到服务器返回的数据后会怎么做呢?答,解析数据,生成渲染树
渲染展现页面是肯定的啦,关键是如何渲染。我们先来看一下浏览器的简单处理步骤:
(1)解析HTML/SVG/XHTML,build DOM树。
(2)解析CSS,build CSSOM树。
(3)build render树。render树并不等同于DOM树,因为一些像Header或display:none的东西就没必要放在render树中了。
(4)reflow。计算每个Element在设备中显示的具体位置。
(5)paint。最后通过调用操作系统Native GUI的API绘制。
二.缓存规则解析
HTTP缓存有多种规则,根据是否需要重新向服务器发起请求来分类,我将其分为两大类(强制缓存,对比缓存)
在详细介绍这两种规则之前,先通过时序图的方式,让大家对这两种规则有个简单了解。
已存在缓存数据时,仅基于强制缓存,请求数据的流程如下:
已存在缓存数据时,仅基于对比缓存,请求数据的流程如下:
我们可以看到两类缓存规则的不同,强制缓存如果生效,不需要再和服务器发生交互,而对比缓存不管是否生效,都需要与服务端发生交互。
两类缓存规则可以同时存在,强制缓存优先级高于对比缓存,也就是说,当执行强制缓存的规则时,如果缓存生效,直接使用缓存,不再执行对比缓存规则。
三.用户行为与缓存
a. 浏览器url回车、页面链接跳转、新开窗口、前进、后退
浏览器发现缓存中有这个文件,就不发送任何请求了,直接去缓存中获取展现。(最快)
b. 按下F5刷新
F5就是告诉浏览器,别偷懒,好歹去服务器看看这个文件是否有过期了。于是浏览器就胆胆襟襟的发送一个请求带上If-Modify-since。
然后服务器发现:诶,这个文件我在这个时间后还没修改过,不需要给你任何信息了,返回304就行了。于是浏览器获取到304后就去缓存中欢欢喜喜获取资源了。
c. 按下Ctrl+F5
这个可是要命了,告诉浏览器,你先把你缓存中的这个文件给我删了,然后再去服务器请求个完整的资源文件下来。于是客户端就完成了强行更新的操作。
参考链接: