You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome DevTools未上报僵尸SSE连接引发请求卡顿问题求助

问题描述

背景

基于HTTP/1.1构建的内部Web应用,未启用TLS,无法使用HTTP/2、HTTP/3或QUIC。客户端包含:

  • 若干静态资源
  • 基于Fetch API的快速API接口
  • 2个并发长连接SSE流
    请求由Nginx服务,问题与Nginx无关。

问题现象

页面刷新后部分请求卡顿数秒,Chrome未立即发送HTTP请求,DevTools无排查线索。已排除高优先级请求干扰、服务器线程问题、QUIC协议问题、缓存磁盘空间问题,最初检查DevTools显示SSE连接不超过2个,但实际触发了Chrome单源最大6个TCP连接的限制。

配置Nginx添加Connection: close头未解决问题。通过Wireshark发现:单源TCP连接数达上限,超出的是未被任何标签页使用、DevTools未显示的僵尸SSE连接,底层TCP连接仍开放。TCP四次握手终止流程在页面刷新、SSE连接被遗弃很久后才启动,且恰好在卡顿请求发起前由Chrome主动触发,连接释放后新请求才发送。


解答

1. 为何SSE连接仍处于开放状态?

  • 页面刷新时,旧页面的EventSource实例若未被主动调用close(),浏览器不会立即触发TCP连接关闭。HTTP/1.1长连接默认复用,浏览器可能延迟回收这类无上下文关联的连接。
  • SSE依赖服务器主动推送数据,若服务器未设置连接超时或发送关闭信号,即使页面已卸载,底层TCP连接仍会保持开放状态,直到浏览器的垃圾回收机制或内部连接清理逻辑触发。
  • 浏览器的连接池管理逻辑可能会保留闲置长连接一段时间,用于后续请求复用,但如果这些连接关联的页面上下文已销毁,就会变成无主的僵尸连接。

2. 如何避免出现僵尸SSE连接?

  • 主动关闭SSE连接:在页面beforeunload或unload事件中,显式调用EventSource.close(),通知浏览器和服务器立即终止连接。示例:
    window.addEventListener('beforeunload', () => {
      if (window.sseConnection) {
        window.sseConnection.close();
      }
    });
    
  • 服务器端设置连接超时:为SSE连接配置超时时间,若一段时间内无数据推送(可配合心跳机制),主动关闭TCP连接,避免连接长期闲置。
  • 添加心跳机制:服务器定期发送心跳帧(比如每隔30秒发送一条空注释:\n\n),浏览器若连续几次未收到心跳,主动关闭连接;服务器也可通过心跳检测客户端是否在线,及时清理无效连接。
  • 避免全局残留实例:将EventSource实例绑定到页面上下文,确保页面卸载时能被正确清理,避免内存泄漏导致连接无法回收。

3. 为何僵尸连接未在Chrome DevTools中上报?

  • Chrome DevTools的网络面板仅追踪当前页面上下文的请求和连接,旧页面卸载后,其关联的连接会从DevTools的监控范围中移除,即使底层TCP连接仍存在。
  • DevTools默认只展示活跃的、属于当前标签页的请求资源,僵尸连接属于无主连接,没有关联的页面上下文,因此不会被显示。
  • Chrome的内部连接管理模块与DevTools的展示逻辑是分离的,DevTools不会暴露系统级的所有TCP连接,仅展示与当前页面请求相关的连接信息。

内容的提问来源于stack exchange,提问作者Matteo T.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 01:21:02