概况
日常开发流程中,免不了要排查接口时长相关问题。本文主要配合案例,解释控制台请求时间线的各个字段含义。
请求流程与字段描述
先来看看chrome对这些字段做出的描述
-
Queueing. 浏览器在以下情况下对请求进行排队:
- 有更高优先级的请求.
- 在同一个源(origin)下已经建立了6条链接, 仅存在于HTTP/1.0 或是 HTTP/1.1 协议.
- 浏览器正在磁盘缓存中短暂分配空间
-
Stalled. 因为 Queueing中的原因而导致的耗时.
-
DNS Lookup. 浏览器正在解析请求的ip地址.
-
Initial connection. 浏览器正在建立链接, 包括TCP握手/重试和协商SSL.
-
Proxy negotiation.浏览器正在与 代理服务器协商.
-
Request sent. 正在发送请求.
-
ServiceWorker Preparation. 浏览器正在建立service worker.
-
Request to ServiceWorker.请求被发送到service worker.
-
Waiting (TTFB) . 浏览器正在等待接收服务器的
第一个字节. TTFB 全称是 Time To First Byte. 此计时包括1次往返延迟和服务器准备响应所花费的时间。. -
Content Download. 浏览器正在从网络获证service worker接收响应. 此值是读取响应正文所花费的总时间。大于预期值可能表示网络速度慢,或者浏览器正忙于执行其他工作,从而延迟响应的读取
-
Receiving Push. 浏览器正在通过HTTP/2服务器接收响应.
-
Reading Push. 浏览器正在读取先前接收的本地数据.
流程模拟
现在node服务器上模拟一个slow接口
// node
mockSlowRequest(res) {
await sleep(5000);
res.end("slow request");
}
前端模拟一个简单的多次调用接口的场景
// js
function fetchSlowRequest() {
fetch("http://localhost:3002/slow");
}
// html
<button onclick="fetchSlowRequest()">发送慢请求</button>
连续点击请求按钮进行接口请求测试
意外收获
第一轮测试得到的网络流水图如下:
emmm, 本以为抓个小贼,没想到捅了老窝。这和预想的也不一致啊。理论上来说同origin下chrome支持最大6条tcp链接,而上面的结果感觉这些请求根本不是异步处理的。
为了探究这个问题,使用chrome自带抓请求工具和分析工具分析刚才的请求过程
TRANSACTION_READ_HEADERS无疑是收到响应头的事件,那这5000ms是正常的,那这个HTTP_CACHE_ADD_TO_ENTRY是啥,为啥耗费这么多的时间呢?
经过一番查找在这里得到了一个比较合理的解释
应该是chrome有个缓存锁逻辑,浏览器对一个资源发起请求前,会先检查本地缓存,此时这个请求对该资源对应的缓存的读写是独占的。我一直调用slow请求,导致了这个缓存被所有请求占用锁死,从而造成这么长时间的stalled时间
回到正题
我直接给请求加上索引
let count = 1;
function fetchSlowRequest() {
fetch("http://localhost:3002/slow" + count++);
}
再重复上述操作,得到如下流水图
可疑,终于符合预期了(为什么只有5条,因为我的favicon占了一条 = =)
可以,完全符合预期
看看slow7的时间线
这里的stalled就是等待Socket Pool,也就是tcp资源池调度的时间,waiting时间也就是等待服务器响应的时间。
request sent耗费时间长的场合我还没怎么见过,也不好模拟,content download的详细分析,可以看我之前的这篇文章