前言
在Web相关的问题中,从输入URL到整个页面加载展示到用户面前这个问题是绕不开的,它主要涉及到网络请求与客户端渲染两个步骤
- 网络请求
- DNS解析
- TCP连接建立
- SSL/TLS隧道建立(HTTPS)
- 发送HTTP请求
- 返回HTTP报文
- 断开SSL/TLS隧道
- 关闭TCP连接
- 客户端渲染
本文主要介绍一下其中的网络请求部分。
DNS解析
相比较于IP地址,以字符串来表示的域名更加符合人类的记忆习惯,因此用户通常使用域名来访问资源,而非IP地址。DNS提供域名与IP的映射服务,解析用户输入的域名为真实IP地址进行访问。
解析流程
- 首先浏览器会查询自身的DNS缓存,此处缓存时间较短,Chrome只有1分钟。
- 如果浏览器的缓存里没有找到的话,则搜索系统自身的DNS缓存。
- 浏览器如果在上述缓存里没有找到对应的条目,则查找本地Host文件,如果在Host文件中查找到对应的IP的话,则使用这个IP。
- 如果在上一步未命中,则向本地DNS服务器发起请求,查询域名对应的IP地址。请求到达服务器后,DNS服务器会首先查询缓存,如果命中,则返回IP地址
- 如果没有找到的话,本地DNS服务器会以递归查询的方式依次向根域名服务器、顶级域名服务器、权威域名服务器发起查询请求,直到获取到IP地址
- 本地DNS服务器会将IP地址返回给浏览器并存入缓存,方便下次查询。
查询流程
性能优化
DNS prefetch:在代码中,经常将一些静态资源放在CDN中,每个CDN地址都要去做下DNS解析,这个会浪费时间,可以通过预先进行DNS解析,然后在请求的时候,DNS已经解析完成就不用等待了。
<!--在head标签中,放在前面-->
<link rel="dns-prefetch" href="//test.com">
TCP连接建立
TCP协议位于传输层,负责提供可靠的字节流服务。
字节流服务:为了方便传输,将大块数据分割成以报文段为单位的数据包进行管理。
可靠的传输服务:将数据准确可靠地传输给对方
为了确保数据传输服务的可靠性,TCP协议采用了三次握手策略:
- 发送端首先发送一个带有SYN标志的数据包给接收端
- 接收端收到后,回传一个带有SYN/ACK标志的数据包传达确认信息
- 发送端再次回传一个带有ACK标志的数据包,握手结束
如果上述过程中某个阶段中断,则TCP协议会再次以相同的次序进行握手操作建立连接
三步握手的目的是让两方都确认对方能够发送接收数据:
- 发送端发出,接收端接收,接收端知道发送端能发送数据
- 接收端发出,发送端接收,发送端知道接收端能发送及接收数据
- 发送端发出,接收端接收,接收端知道发送端能接收数据
SSL/TLS隧道建立(HTTPS)
说到SSL/TLS需要首先介绍下HTTPS,HTTPS是加上了加密处理、认证机制以及完整性保护的HTTP,它并非是应用层的一种新协议,而是将HTTP通信接口部分使用SSL/TLS协议代替。通常,HTTP会直接和TCP进行通信,而加上这部分处理后,则演变为先和SSL/TLS通信,再由SSL/TLS和TCP进行通信了,相当于加了一层SSL/TLS外壳的HTTP。
SSL协议,是一种安全传输协议,最初是由 Netscape 在1996年发布,由于一些安全的原因SSL v1.0和SSL v2.0都没有公开,直到1996年的SSL v3.0。TLS是SSL v3.0的升级版,目前市面上所有的HTTPS都是用的是TLS,而不是SSL。
SSL/TLS是独立于HTTP的协议,也可以用于其他应用层的协议上,具体的加密等功能本文不做深入探讨,在这里讲一下SSL/TLS隧道建立的过程(四次握手):
第一次握手
- 客户端发送Client Hello报文开始TLS/SSL通信。报文中包含客户端支持的TLS/SSL的指定版本以及加密组件列表
第二次握手
- 服务端支持TLS/SSL通信时,会返回Server Hello报文。里面同样包含支持的TLS/SSL的指定版本以及加密组件列表
- 服务端发送Certificate报文,报文中包含公开密钥证书
- 服务端发送Server Hello Done报文通知客户端,TLS/SSL初步握手协商结束
第三次握手
- 客户端发送Client Key Exchange报文,报文中包含随机密码串,该报文使用第一次握手步骤3中的公开密钥进行加密
- 客户端继续发送Change Cipher Spec报文,该报文负责告知后续通信的加密密码串方式
- 客户端发送Finished报文,报文包含连接至今全部报文的整体校验值。本次握手是否成功,要以服务器能否正确解密该报文为判断标准
第四次握手
- 服务端发送Change Cipher Spec报文
- 服务端发送Finished报文,SSL/TLS通信隧道建立。后续开始发送HTTP请求
发送HTTP请求
HTTP协议属于TCP/IP族协议,用于主机之间的网络通信。
缓存机制
首次请求
- HTTP首次发起请求时,会先由浏览器查看是否有缓存数据
- 在确认无缓存数据后向服务器发起请求
- 服务器会返回数据以及缓存规则,浏览器在接收后存储缓存的数据以及相应的缓存规则
缓存机制下的请求
HTTP的缓存主要分为两种:
- 强缓存:请求的资源在缓存中未过期时,不与服务器进行交互,直接使用缓存中的数据
- 协商缓存:当强缓存过期未命中或者
Cache-Control中有must-revalidate标识表示每次必须验证资源状态时,使用协商缓存去处理缓存文件。从缓存数据库中取出缓存的标识,向服务器发送请求验证请求的数据是否更新,如果已经更新则返回新的数据,如果未更新则使用缓存中的数据
整体流程
协议层传输过程
利用TCP/IP协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则往应用层往上走。
- 首先作为发送端的客户端在应用层(HTTP协议)发出HTTP请求,获取 Web 页面
- 接着,为了传输方便,在传输层(TCP 协议)把从应用层处收到的数据(HTTP 请求报文)进行分割,并在各个报文上打上标记序号及端口号后转发给网络层。
- 在网络层(IP 协议),增加作为通信目的地的 MAC 地址后转发给链路层。这样一来,发往网络的通信请求就准备齐全了
- 接收端的服务器在链路层接收到数据,按序往上层发送,一直到应用层。当传输到应用层,才能算真正接收到由客户端发送过来的 HTTP 请求。
返回HTTP报文
返回状态码标识请求结果
- 2XX:请求被正常处理
- 3XX:浏览器需要执行某些特殊的处理以正确处理请求
- 4XX:客户端发生错误,请求未能成功
- 5XX:服务器端发生错误,请求未能成功
断开SSL/TLS隧道
SSL/TLS隧道的断开由客户端发起,通过发送close_notify报文断开
关闭TCP连接
在关闭连接时,TCP通信双方一共需要操作四次,称为四次挥手:
- 客户端向服务端发送FIN标记的报文
- 服务端收到客户端发送的报文后,发送一个包含确认序号ACK的报文
- 服务端向客户端发送FIN标记报文
- 客户端在收到FIN标记报文后,会向服务端发送确认序号ACK报文,然后经过两个MSL时长后断开连接
MSL(Maximum Segment Lifetime):最大报文生存时间,指报文发送和接收的最长时间
第二次挥手时,服务端可能还有数据报文需要发送,因此会先发送ACK报文告知客户端已知悉要断开请求,在处理完数据报文后会发送FIN报文给客户端,这样就保证了数据通信的正常可靠性。