连接复用时为什么 fetch 还是新建 TCP 连接?

FSD-倩云 阅读 62

我在做性能优化时发现,明明连续发了几个 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'));
我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
码农翌萌
遇到这种情况,通常是浏览器或者网络层在某些情况下没有复用TCP连接。虽然HTTP/1.1和HTTP/2都支持连接复用,但有几个常见的原因可能导致每次请求都新建了TCP连接:

1. 浏览器并发限制。大多数浏览器对同一个域名的并发请求数有限制,如果之前的请求还没有完成,新的请求可能会被阻塞或者导致新建连接。
2. 请求头或者响应头设置问题。虽然你说确认了Connection: keep-alive,但是其他头信息也可能影响连接复用,比如Cache-ControlContent-Encoding的设置。
3. HTTPS/TLS握手。如果使用HTTPS,每次新建连接都会进行TLS握手,这个过程比较耗时,有时候会看到新建连接的行为,但实际上是在复用之前已经建立好的安全通道。
4. 浏览器缓存机制。如果响应可以被缓存,浏览器可能不会发起新的请求而是从缓存中读取数据,这也会看起来像是新建了连接。

常见的解决方案是:
- 检查网络请求是否真的被阻塞,可以使用浏览器的网络调试工具查看请求的时间线和状态。
- 确认所有请求头和响应头都没有阻止连接复用的因素。
- 尝试减少并发请求的数量,看看是否有帮助。
- 如果可能,尽量减少不同类型的资源请求,统一资源类型有助于复用连接。
- 确保服务器配置正确,支持并启用了HTTP/1.1持久连接或者HTTP/2。

如果以上方法都不奏效,可能需要更详细的分析网络流量,看看具体的请求和响应头是什么样的,或者考虑联系服务端同事确认一下服务器的配置。
点赞
2026-03-25 08:07
UX恒菽
UX恒菽 Lv1
问题很可能是第一个请求还没完成,第二个请求就发出了,浏览器来不及复用连接。

试试改成串行等待每个请求完成后再发下一个:

await fetch('/api/data1');
await fetch('/api/data2');
await fetch('/api/data3');
或者给 fetch 加上 keepalive: true 强制保持连接:

fetch('/api/data1', { keepalive: true })
.then(res => res.json())
.then(() => fetch('/api/data2', { keepalive: true }))
.then(res => res.json())
.then(() => fetch('/api/data3', { keepalive: true }));


如果你的请求带自定义头或者用了非简单 Content-Type,浏览器会先发 OPTIONS 预检,这个也不会复用连接,记得检查一下。
点赞
2026-03-19 22:15