连接复用时为什么 fetch 还是新建 TCP 连接?
我在做性能优化时发现,明明连续发了几个 fetch 请求到同一个域名,但浏览器 DevTools 里显示每个请求都新建了 TCP 连接,不是说 HTTP/1.1 支持 keep-alive、HTTP/2 支持连接复用吗?是不是我哪里写错了?
我试过加 withCredentials 和 mode: ‘cors’,也确认服务端返回了 Connection: keep-alive,但还是没复用。代码大概是这样:
fetch('/api/data1')
.then(res => res.json())
.then(() => fetch('/api/data2'))
.then(res => res.json())
.then(() => fetch('/api/data3'));
1. 浏览器并发限制。大多数浏览器对同一个域名的并发请求数有限制,如果之前的请求还没有完成,新的请求可能会被阻塞或者导致新建连接。
2. 请求头或者响应头设置问题。虽然你说确认了
Connection: keep-alive,但是其他头信息也可能影响连接复用,比如Cache-Control或Content-Encoding的设置。3. HTTPS/TLS握手。如果使用HTTPS,每次新建连接都会进行TLS握手,这个过程比较耗时,有时候会看到新建连接的行为,但实际上是在复用之前已经建立好的安全通道。
4. 浏览器缓存机制。如果响应可以被缓存,浏览器可能不会发起新的请求而是从缓存中读取数据,这也会看起来像是新建了连接。
常见的解决方案是:
- 检查网络请求是否真的被阻塞,可以使用浏览器的网络调试工具查看请求的时间线和状态。
- 确认所有请求头和响应头都没有阻止连接复用的因素。
- 尝试减少并发请求的数量,看看是否有帮助。
- 如果可能,尽量减少不同类型的资源请求,统一资源类型有助于复用连接。
- 确保服务器配置正确,支持并启用了HTTP/1.1持久连接或者HTTP/2。
如果以上方法都不奏效,可能需要更详细的分析网络流量,看看具体的请求和响应头是什么样的,或者考虑联系服务端同事确认一下服务器的配置。
试试改成串行等待每个请求完成后再发下一个:
或者给 fetch 加上
keepalive: true强制保持连接:如果你的请求带自定义头或者用了非简单 Content-Type,浏览器会先发 OPTIONS 预检,这个也不会复用连接,记得检查一下。