从输入URL到页面展示的过程——详解网络与渲染流程

1,971 阅读11分钟

前言

为了方便接下来的介绍,我们首先要了解计算机网络体系结构,如下图:

从 url 输入到页面展现的总体过程

  1. 用户输入

  2. 检查缓存

  3. DNS 解析

  4. 建立 TCP 连接(三次握手)

  5. HTTP 请求与响应

  6. 关闭 TCP 连接(四次挥手)

  7. 准备渲染进程

  8. 提交文档

  9. 渲染阶段

1 用户输入

当用户在地址栏中输入一个查询关键字时,地址栏会判断是搜索内容,还是URL

  1. 如果是搜索内容,地址栏会使用浏览器默认的搜索引擎,来合成新的带搜索关键字的 URL。
  2. 如果判断输入内容符合 URL 规则,则地址栏会根据规则,把这段内容加上协议,合成为完整的 URL。

2 检查缓存

网络进程会查找本地缓存是否缓存了该资源。

  1. 如果有缓存资源,那么直接返回资源给浏览器进程;
  2. 如果在缓存中没有查找到资源,那么直接进入网络请求流程。

3 DNS 解析

3.1 什么是 DNS

域名系统 DNS是互联网使用的命名系统,用来把域名转换为 IP 地址。

3.2 DNS 解析的查询过程

DNS 解析过程中,主机向本地域名服务器的查询一般都是采用递归查询,本地域名服务器向根域名服务器的查询通常是采用迭代查询

以上图(a)例,具体的 DNS 解析步骤为:

  1. 主机 m.xyz.com 先向其本地域名服务器 dns.xyz.com 进行递归查询。

  2. 本地域名服务器采用迭代查询。它先向一个根域名服务器查询。

  3. 根域名服务器告诉本地域名服务器,下一次应查询的顶级域名服务器 dns.com 的 IP 地址。

  4. 本地域名服务器向顶级域名服务器 dns.com 进行查询。

  5. 顶级域名服务器 dns.com 告诉本地域名服务器,下一次应查询的权限域名服务器 dns.abc.com 的 IP 地址。

  6. 本地域名服务器向权限域名服务器 dns.abc.com 进行查询。

  7. 权限域名服务器 dns.abc.com 告诉本地域名服务器,所查询的主机的 IP 地址。

  8. 本地域名服务器最后把查询结果告诉主机 m.xyz.como。

思考:DNS 为什么使用 UDP 协议作为传输层协议? 答:主要原因是为了避免使用 TCP 协议时造成的连接时延。

3.3 DNS 优化

  1. DNS 缓存: 浏览器缓存,系统缓存,路由器缓存,IPS 服务器缓存,根域名服务器缓存,顶级域名服务器缓存,主域名服务器缓存。通过缓存直接读取域名相对应的 IP,减去了繁琐的查找 IP 的步骤,大大加快访问速度。

  2. DNS 负载均衡:使用 CDN 进行负载均衡,利用 DNS 的重定向技术,同步服务器运行情况,然后根据该情况及时适当调整调度策略,从而使得负载均衡能力大大提高。

4 建立 TCP 连接

注:本节大部分内容摘自参考[1]。

4.1 什么是 TCP

TCP 传输控制协议有以下这些特点:

  1. TCP 是面向连接运输层协议。

  2. 每一条 TCP 连接只能有两个端点,每一条 TCP 连接只能是点对点的。

  3. TCP 提供可靠交付的服务,即传输的数据无差错、不丢失、不重复、按序到达。

  4. TCP 提供全双工通信

  5. 面向字节流

4.2 TCP 报文段

TCP 报文段的首部格式:

其中部分字段的含义:

  • 序号:指的是本报文段所发送的数据的第一个字节的序号。

  • 确认号:是指期望收到对方下一个报文段的第一个数据字节的序号。若确认号 =N, 则表明:到序号 N-1 为止的所有数据都己正确收到。

  • 确认 ACK:仅当 ACK= 1 时确认号字段才有效。当 ACK=0 时,确认号无效。 TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 置 1。

  • 同步 SYN:在连接建立时用来同步序号。当 SYN= 1 而 ACK = 0 时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使 SYN=1 和 ACK= 1。因此, SYN 置为 1 就表示这是一个连接请求或连接接受报文。

  • 终止 FIN:用来释放连接。但 FIN 置为 1 时,表示报文发送发的数据已发送完毕,并要求释放运输连接。

4.3 三次握手的具体过程

TCP 连接的过程又称为三次握手,示意图如下:

三次握手的具体过程: 一开始, B 的 TCP 服务器进程先创建传输控制块 TCB,准备接受客户进程的连接请求。然后服务器进程就处于 LISTEN (收听)状态,等待客户的连接请求。如有,即作出响应。

  1. A 的 TCP 客户进程也是首先创建传输控制模块 TCB。然后,在打算建立 TCP 连接时, 向 B 发出连接请求报文段,这时首部中的同步位 SYN = 1 ,同时选择一个初始序号 seq = x。TCP 规定, SYN 报文段(即 SYN= 1 的报文段)不能携带数据,但要消耗掉一个序号。 这时, TCP 客户进程进入 SYN-SENT (同步己发送)状态。

  2. B 收到连接请求报文段后,如同意建立连接,则向 A 发送确认。在确认报文段中应把 SYN 位和 ACK 位都置 1 ,确认号是 ack = x + 1,同时也为自己选择一个初始序号 seq = y。 请注意,这个报文段也不能携带数据,但同样要消耗掉一个序号。这时 TCP 服务器进程进 入 SYN-RCVD (同步收到)状态。

  3. TCP 客户进程收到 B 的确认后,还要向 B 给出确认。确认报文段的 ACK 置 1 ,确认号 ack=y+1,而自己的序号 seq = x + 10。TCP 的标准规定, ACK 报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍是 seq=x+1。这时, TCP 连接己经建立, A 进入 ESTABLISHED (己建立连接)状态。 当 B 收到 A 的确认后,也进入 ESTABLISHED 状态。

思考:为什么 A 最后还要发送一次确认呢? 这主要是为了防止己失效的连接请求报文段突然又传送到了服务器,因而产生错误。

5 HTTP 请求与响应

5.1 HTTP 简介

HTTP 是基于 TCP/IP 协议的应用层协议。它的主要特点是:

  1. 灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记。

  2. 无状态:HTTP 协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

  3. 请求-应答模式,通常而言,就是一方发送消息,另外一方要接受消息,或者是做出相应等。

  4. 可靠传输,HTTP 是基于 TCP/IP,因此把这一特性继承了下来。

5.1.1 请求报文

HTTP 请求报文由请求行请求头请求体组成。

5.1.2 响应报文

HTTP 响应报文由响应行响应头响应体组成。

在响应报文中,Content-Type 字段的值:

  1. 如果被浏览器判断为下载类型,那么该请求会被提交给浏览器的下载管理器,同时该 URL 请求的导航流程就此结束。
  2. 但如果是 HTML,那么浏览器则会继续进行导航流程。

查阅资料:常见状态码

6 关闭 TCP 连接

数据传输完成后,如果没有设置 Connection:Keep-Alive,将关闭 TCP 连接。

关闭 TCP 连接的具体步骤,如下图:

  1. A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。 A 把终止控制位 FIN 置 1 ,序号 seq = u,u 等于前面已传送过的数据的最后一个字节的序号加 1 。

  2. B 收到连接释放报文段后,则发出确认,确认号是 ack = u + 1,序号是 v,等于 B 前面已传送过的数据的最后一个字节的序号加 1 。这时的 TCP 连接处于半关闭状态,即 A 已经没有数据要发送了,但 B 若发送数据, A 仍要接收。

  3. 若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接。这时 B 发出的连接释放报文段中 FIN = 1 。现假定 B 的序号为 w (在半关闭状态 B 可能又发送了一些数据)。B 还必须重复上次已发送过的确认号 ack = u + 1 。

  4. A 在收到 B 的连接释放报文段后,必须对此发出确认。在确认报文段中把 ACK 置 1,确认号 ack = w + 1 ,而自己的序号是 seq=u+1。然后进入到 TIME-WAIT (时间等待)状态。现在 TCP 连接还没有释放掉,必须 2MSL(最长报文段寿命) 时间后, A 才进入到 CLOSED 状态,才能开始建立下一个新的连接。

思考:为什么 A 在 TIME-WAIT 状态必须等待 2MSL 的时间呢?

  1. 为了保证 A 发送的最后一个 ACK 报文段丢失时,A 可以收到 B超时重传FIN + ACK 报文段的确认。

  2. 防止"己失效的连接请求报文段"出现在本连接中。

7 准备渲染引擎

process-per-site-instance:这是一种浏览器的默认策略,具体而言就是:如果从一个页面打开了另一个新页面,而新页面和当前页面属于同一站点的话,那么新页面会复用父页面的渲染进程。

打开新页面采用的渲染进程策略是:

  1. 如果从 A 页面打开 B 页面,且二者都属于同一站点的话,那么 B 页面复用 A 页面的渲染进程;
  2. 如果是其他情况,浏览器进程则会为 B 创建一个新的渲染进程。

8 提交文档

提交文档:就是指浏览器进程将网络进程接收到的 HTML 数据提交给渲染进程。

  1. 浏览器发出“提交文档”的消息给渲染进程
  2. 渲染进程收到消息后,会和网络进程建立传输数据的“管道”
  3. 文档数据传输完成
  4. 渲染进程返回“确认提交”的消息给浏览器进程
  5. 浏览器收到“确认提交”的消息后,会更新浏览器的页面状态

9 渲染阶段

渲染流水线:渲染模块在执行过程中会被划分为很多子阶段,这些子阶段称为流水线。

渲染引擎的工作流程:以 HTML/JavaScript/CSS 等文件作为输入,以可视化内容作为输出。 具体步骤:

  1. HTML 转换为 DOM树

  2. CSS 转换为 CSSOM

  3. 合并DOM和CSSOM,生成渲染树(这棵树中不包含不可见节点)

  4. 根据渲染树来布局,以计算每个节点的几何信息。

  5. 对布局树进行分层,生成分层树

  6. 为每个图层生成绘制列表

  7. 合成线程将图层分成图块(tile),并在光栅化(raster)线程池中将图块转换成位图

  8. 合成线程发送绘制图块命令 DrawQuad 给浏览器进程

  9. 浏览器进程生成页面,并显示到显示器上

渲染流水线示意图,如下:

reflow(重排)、repaint(重绘)和 composite (合并)是什么?

reflow:更新元素的几何属性(如:改变元素的宽度、高度等)时,将发生reflow。重排需要更新完整的渲染流水线,所以开销也是最大的。

repaint:更新元素的绘制属性(如:更改元素的背景颜色)时,将发生repaint。重绘省去了布局和分层阶段,所以执行效率会比重排操作要高一些。

composite:更改一个既不要布局也不要绘制的属性(如:transform)时,将发生composite。相对于重绘和重排,合成能大大提升绘制效率。

如何减少reflow(重排)、repaint(重绘)?

  1. 将经常改变的元素,设置定位为fix或absolute,以避免影响其周围元素
  2. 避免不必要的CSS选择器
  3. 对移除或者隐藏的元素进行修改
  4. 通过临时存储值,减少测量次数,等等...

参考

  1. 《计算机网络第七版》-章节 5.3、5.5、5.9、6.1,谢希仁

  2. 浏览器工作原理与实践

  3. Web Performance: Minimising DOM Reflow / Layout Shift