理解Chrome请求流程

2019-10-27

Timing Tab

Chrome的DevTools中提供了对请求的时间分析,如配图所示。

对每个请求,Chrome统计了它们不同阶段的通信时间,包括:

  • Queueing
  • Stalled
  • DNS Lookup
  • Proxy negotiation
  • Initial Connection /Connecting
  • SSL
  • Request sent
  • ServiceWorker Preparation
  • Request to ServiceWorker
  • Waiting(TTFB)
  • Content Download
  • Receiving Push
  • Reading Push

Queueing

Queueing意味着请求没有马上发生,加入队列排队等候。导致这种情况一般可能的原因有:

  • 有更高优先级的请求
  • 请求等待即将被释放的TCP socket
  • 与当前域名的TCP连接数已满上限6个(仅对HTTP/1.0和HTTP/1.1生效)
  • 浏览器正在分配磁盘缓存(一般非常短暂)

要注意的是第三点中的6个TCP连接数上限在不同浏览器中也不相同,根据HTTP协议的规定限制数量应为2个,但是各浏览器有不同的标准:

---------------------------------
| Browser | Maximum connections |
|---------|---------------------|
| IE7     | 2                   |
| IE8/IE9 | 6                   |
| IE10    | 8                   |
| IE11    | 13                  |
| FireFox | 6                   |
| Chrome  | 6                   |
| Safari  | 6                   |
| Opera   | 6                   |
| iOS     | 6                   |
| Android | 6                   |
---------------------------------

Stalled

当请求被放入队列后,就会有阻塞的时长。Stalled描述的是请求被发送之前等待的时长,一般就是Queueing中的原因导致的。除此之外,Stalled还包含了代理协商的时长。

DNS Lookup

进行DNS查找(域名解析)的时长。每次请求一个新的域名的时候,需要进行一次完整的域名解析过程。

Proxy negotiation

浏览器与代理服务器进行协商的过程。

Initial Connection /Connecting

建立连接的时长,包括TCP握手/重试的时长和SSL协商的时长。

SSL

完成SSL握手的时长。

Request sending/sent

发布请求的过程时间,一般非常快。

ServiceWorker Preparation

浏览器启动Service Worker的时长。

Request to ServiceWorker

请求被发送至Service Worker的时长。

Waiting(TTFB)

等待最初相应的时长,A.K.A Time To First Byte。这个时长等于请求发送至服务器的延迟、响应返回至客户端的延迟、服务器处理请求的时间之和。

Content Download

浏览器接收完整相应的时长。

Receiving Push

浏览器接收服务器(HTTP/2)推送数据的时长。

Reading Push

浏览器读取接收到数据的时长。

结合上图为例,可以看到请求图中接口的时间消耗:

  • 请求放入队列花费1.94ms
  • 请求在队列中被阻塞了2.25ms直至开始发送请求
  • 域名解析花费0.41ms
  • 与服务器建立连接,花费72.11ms,其中,完成SSL协商,花费的38.24ms是包含在72.11ms内的
  • 发送请求,花费0.17ms
  • 发送后到接收第一个响应数据间隔了36.07ms
  • 完成响应报文的下载花费了2.00ms

本次请求一共花了115.16ms(数据求和为114.95ms,推断各阶段间有细微执行时间没有统计到)。

Full Request Process

现在结合Chrome的DevTools信息,再来更新一下从请求到页面展示的流程,以用户在浏览器中输入www.baidu.com为例,其中Chrome相关内容加粗显示:

  • 请求准备部分
    • 用户在浏览器中输入www.baidu.com,按下回车
    • Chrome开始准备请求,如果满足被Queued规则的话放入队列中等待
    • 此时Chrome会分配磁盘的缓存空间为后续缓存操作做准备
    • 队列任务等待结束,开始准备发送请求;非队列任务准备发送请求
    • Chrome查询是否有可用的磁盘或内存缓存:
      • 如有且新鲜,则获取缓存内容,跳过解析和发起请求过程
      • 如果没有缓存,继续按照后续步骤发起请求
  • 域名解析部分
    • 浏览器解析URL,获取协议、路径和端口号
    • 浏览器组装一个HTTP请求报文
    • 浏览器进行域名解析,获取主机的IP地址,主要通过:
      • 浏览器对域名解析结果的缓存
      • 本机对域名解析结果的缓存
      • hosts文件
      • 路由器缓存
      • ISP DNS缓存
      • DNS递归查询
  • 发起请求部分
    • 获取到IP后打开一个socket,与目标建立TCP连接,进行三次握手,细节太多受限篇幅不在此叙述,花费时间即为Initial Connection中减去SSL相关的部分
    • 如果为HTTPS请求,进行SSL握手,花费时间为Timing中SSL部分
    • 发送HTTP请求
  • 接收响应部分
    • 服务器检查HTTP请求头是否包含缓存验证信息:
      • 验证缓存新鲜,返回304
      • 验证不通过,处理请求并准备HTTP相应
    • HTTP响应通过建立的TCP连接发送给浏览器,首个报文抵达时间即为Waiting(TTFB),完整接收时长为Waiting+Content Download时长
    • 浏览器视情况保留TCP连接或进行四次挥手结束连接
    • 浏览器根据响应状态码进行处理
    • 如果响应资源可以缓存,进行缓存
    • 对压缩(如gzip)的响应进行解码
  • 处理响应资源,假设资源为HTML文档(后续过程可能没有严格的先后顺序):
    • 构建DOM树
    • 针对构建过程中遇到的图片、样式、js启动下载
    • 构建CSSOM树
    • 根据DOM树和CSSOM树构建渲染树
    • JS解析
    • 显示页面

Ref

Understanding Resource Timing

chromium.org – Issue: Match Firefox’s per-host connection limit of 15

Service Worker