背景
领导要优化性能,指着 Performance 报告说:小B,快去看看,这些请求为什么头和尾巴那么长,我们是技术部门,任何一点优化都不能放过,懂?
小B:....我懂你个大头鬼
Chrome网络请求耗时分析
network工具能看到http请求耗时,我先贴一个官方解释,这年头官方最靠谱:
- **Queueing**. The browser queues requests when:
- There are higher priority requests.
- There are already six TCP connections open for this origin, which is the limit. Applies to HTTP/1.0 and HTTP/1.1 only.
- The browser is briefly allocating space in the disk cache
- **Stalled**. The request could be stalled for any of the reasons described in **Queueing**.
- **DNS Lookup**. The browser is resolving the request's IP address.
- **Initial connection**. The browser is establishing a connection, including TCP handshakes/retries and negotiating an SSL.
- **Proxy negotiation**. The browser is negotiating the request with a [proxy server](https://en.wikipedia.org/wiki/Proxy_server).
- **Request sent**. The request is being sent.
- **ServiceWorker Preparation**. The browser is starting up the service worker.
- **Request to ServiceWorker**. The request is being sent to the service worker.
- **Waiting (TTFB)** . The browser is waiting for the first byte of a response. TTFB stands for Time To First Byte. This timing includes 1 round trip of latency and the time the server took to prepare the response.
- **Content Download**. The browser is receiving the response, either directly from the network or from a service worker. This value is the total amount of time spent reading the response body. Larger than expected values could indicate a slow network, or that the browser is busy performing other work which delays the response from being read.
下面是我的理解:
- Queueing:
请求排队时间,在这段时间,浏览器并没有接收到要发送这个请求的命令。有三种情况可能排队:
1. 有优先级更高的请求需要发送,优先级则根据文件类型进行区分。通常,html,js,css为主要文件,该种类型文件等候时间较短;而其他类型,如jpg,png或者媒体文件,字体文件等则等候时间较长,等待时间长度较长时,将会导致文件加载缓慢,也就是常说的加载时挂起;
2. 同域名下当前有6个TCP连接了,需要等待其中某个请求结束释放TCP连接,才能轮到本请求
3. 生成磁盘缓存条目所用的时间(通常非常迅速)。但实际情况看, - Stalled:浏览器得到要发出请求的指令后,到请求可以发出的等待时间,Chrome自己说上述能造成 Queueing 的原因都可能引起 Stalled
- DNS Lookup:DNS解析时间,如果解析过就会在本地缓存下来,后面同个域名就很快
- Initial connection:建立TCP连接(握手)和SSL时间
- Proxy negotiation:浏览器与代理协商的时间
- Request sent:请求第一个字节发出前到最后一个字节发出后时间
- Waiting(TTFB,Time to First Byte):请求发出后,到收到响应的第一个字节所花费的时间
- Content Download:收到响应的第一个字节,到接收完最后一个字节的时间,就是下载时间。可以是从网络返回的,也可以是从Service Worker返回的。
如果比预期时间长,原因可能是网络太慢(下载数据慢)或者浏览器忙于其他工作而没开始读返回
其他的都很清楚,就 Stalled不太清楚,后来又看到一段Stalled的解释,文章在后面会贴出来,大概结论是:
1,单一服务发送时候stalled过长,往往是丢包所致,这也意味着网络或服务端有问题。
2,多个服务并发导致stalled过长,是浏览器对同一个主机域名的并发连接数有限制,过长的请求是被阻塞了,处在队列中等待tcp连接
分析
打开F12,随便找个请求,可以看到耗费时长如下:
我们这里看出,Queueing -> initial connection -> Request sent -> Waiting -> Content Download 是串行的,这从概念上也很好理解。ssl耗时属于initial connection的一部分。问题是,这里还有个Stalled,它是串行的吗?我们加一下时间,发现在这里,它的耗时是单独计算的,总耗时 = Stalled + 前面的提到的其他耗时
但真的是这样?我们看下一张图
一眼看出,Stalled 和Initial connection 耗时是会重叠的,这里我其实非常不明白!Stalled阶段不是还没发请求吗?为什么Initial connection又开始Tcp连接了呢?stalled到底是什么原因造成的?谁来救救我!!!
TCP复用
上文提到了,Chrome浏览器同域名下最多有6个TCP连接,请求超过这个数就要等待,这又是什么呢?我们先简单了解下 HTTP 协议
HTTP/1.0
与本文无关的省略,只需知道,HTTP 这个应用层协议是以 TCP 为基础来传输数据的。当你想访问一个资源时,需要先解析这个资源的 IP 地址和端口号,从而和这个 IP 和端口号所在的服务器建立 TCP 连接(三次握手),然后 HTTP 客户端发起服务请求报文,服务器对服务器的请求报文做出响应,客户端收到所有响应后就会关闭 TCP 连接(四次挥手)
在 HTTP/1.0 协议下,每次 HTTP 请求都会建立 TCP 连接,等这次请求结束后, TCP 连接就会关闭,后续请求就会一直重复 TCP 连接/关闭动作
HTTP/1.1
HTTP 1.1 允许 HTTP 在执行完一次事务之后将连接保持在打开状态,也就是不断开 TCP 连接,以便于下一次的 HTTP 事务能够复用这条连接。
在一次 HTTP 事务结束之后仍旧保持打开状态的 TCP 连接被称为持久连接。
持久连接
持久连接通常可以称为 Keep-Alive。
在 HTTP/1.0 中其实也可以开启持久连接,这就需要在请求头中加入字段:
Connection: Keep-Alive
当服务端收到请求时,返回请求加上同样header
Connection: Keep-Alive
在 HTTP/1.1 中,持久连接是默认开启的。如果需要关闭 Keep-Alive,则请求添加如下头:
Connection: close
如果 TCP 连接一直开着,但后面又没 HTTP 请求了,不就造成资源浪费了?尤其是服务端需要对接那么多客户端?
答案是为了避免资源浪费的情况,服务端一般会设置 keep-alive的超时时间。比如设置了 HTTP 长连接的超时时间是 60 秒,服务端就会启动一个定时器,如果客户端在完后一个 HTTP 请求后,在 60 秒内都没有再发起新的请求,定时器的时间一到,就会触发回调函数来释放该连接。
TCP 的Keep-Alive:上面说的是持久连接,也就是 HTTP 的keep-alive,但有一种说法是 TCP的keep-alive,其实也就是 TCP 保活机制。在一定时间段里如果没有收到请求,那么保活机制会建个的发送探测报文,如果都没得到相应,那这个 TCP 可能就出现问题了,就会通知到上层应用
常见问题
- 网页中的图片资源为什么分放在不同的域名下?
我们已经知道,浏览器对并发请求的数目限制是针对域名的(也就是 TCP 连接个数),即针对同一域名(包括二级域名)在同一时间支持的并发请求数量的限制。如果请求数目超出限制,则会阻塞。因此,网站中对一些静态资源,使用不同的一级域名,可以提升浏览器并行请求的数目,加速界面资源的获取速度。
- 浏览器与服务器建立一个TCP连接后,是否会在完成一个http请求后断开?什么条件下会断开?
HTTP/1.0 中,该请求结束后就断开,HTTP/1.1 将
Connection写入了标准,默认值为keep-alive。除非强制设置为Connection: close,才会在请求后断开TCP连接。
- 一个TCP连接可以同时发送几个HTTP请求?
HTTP/1.1 中,单个TCP连接,在同一时间只能处理一个 HTTP 请求,虽然存在Pipelining技术支持多个请求同时发送,但由于实践中存在很多问题无法解决,所以浏览器默认是关闭,所以可以认为一个 TCP 在某一时间只能发一个 HTTP 请求
HTTP2 提供了多路传输功能,多个http请求,可以同时在同一个TCP连接中进行传输
- 浏览器 HTTP 请求的并发性是如何体现的?
浏览器会同时和服务器建立多个 TCP 连接,在同一个TCP连接上
顺序处理多个 HTTP 请求。所以浏览器的并发性就体现在可以建立多个TCP连接上。
Chrome浏览器最多允许对同一个域名Host建立6个TCP连接,不同的浏览器有所区别
- 为什么要限制 TCP 连接个数?不应该越多越快吗?
需考虑浏览器和服务器压力,以及恶意攻击(Dos)的可能性
- 为什么有的时候刷新页面不需要重新建立 SSL 连接?
TCP 连接有的时候会被浏览器和服务端维持一段时间。TCP 不需要重新建立,SSL 自然也会用之前的