# 多开几个标签页挂 EventSource，新连接失败是撞上限了吗？

**URL:** <https://www.shiqidu.com/t/topic/1920>\
**Category:** 问题求助\
**Tags:** JavaScript, 前端开发, 浏览器\
**Created:** [2026 年11 月 3 日 13:17 UTC](https://www.shiqidu.com/t/topic/1920 "2026-11-03T13:17:47Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

作者： ![shiqidu\_editor](https://www.shiqidu.com/user_avatar/www.shiqidu.com/shiqidu_editor/32/528_2.png) [@shiqidu\_editor](https://www.shiqidu.com/u/shiqidu_editor)\
发布日期： [2026 年11 月 3 日 13:17 UTC](https://www.shiqidu.com/t/topic/1920/1 "2026-11-03T13:17:47Z")

</div>

进度页、通知条、后台任务面板各自 `new EventSource(...)`，一个标签还好使。同站点再开几个标签，新的连接开始挂起，或在失败和自动重连之间抖。前端半截 JSON 怎么拼，站里[另一篇](https://www.shiqidu.com/t/topic/1831)写过。这篇只盯浏览器对 Server-Sent Events 的连接模型，对照 MDN 的 [Using server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)。

## EventSource 本身在干什么

MDN 说：SSE 是一条单向连接，浏览器用 `EventSource` 收服务器推过来的事件，不能像 WebSocket 那样从客户端往同通道发事件。构造时传入生成事件的 URL。跨源时还可以带 `withCredentials` 选项。

默认行为里，客户端和服务器之间的连接若断开，浏览器会自动重连。要真正停掉，调用 `.close()`。只关标签却在别处仍握着实例、或错误回调里又 new 了一个，连接数会在你看不见的地方叠上去。调试时打开多个预发标签，每人一条 SSE，名额会很快被吃满。

服务端响应的 MIME 类型应是 `text/event-stream`。事件流按字段组织，常见有：

- `event`：具名事件类型。没有的话走 `message`
- `data`：载荷。多行 `data:` 会拼成一段
- `id`：更新 Last-Event-ID
- `retry`：重连等待毫秒数

以冒号开头的行是注释，可用来保活。这些是协议层约定，跟「能同时开几条连接」是两层问题。后端格式对了，前端仍可能因为连接名额满了而表现为「连不上」或疯狂重试。

## 连接数上限 MDN 怎么写

文档有一段醒目说明：在非 HTTP/2 场景下，SSE 会撞上最大打开连接数限制。多标签时尤其疼，因为限制是按浏览器计的，而且数字很低——文中写的是 **6** 。Chrome 与 Firefox 上该问题被标成 **Won’t fix** 。限制粒度是浏览器 + 域名：对 `www.example1.com` 可以开到那一档上限，对另一个域名再各算一档。

走 HTTP/2 时，同时存在的 HTTP 流数量由服务器与客户端通过 SETTINGS 协商，文档写默认常为 **100** 。也就是说，同域多标签在 HTTP/1.1 上很容易摸到个位数上限。升级到 HTTP/2 后，上限通常宽得多，但仍不是「无限开标签」。MDN 这段明确点名的是 HTTP/2 协商。具体站点是不是已经上了 h2，以浏览器 Network 面板为准。

所以「新标签连不上」优先核对：页面是不是还在 HTTP/1.1。有多少标签／iframe 各自持有未 `close` 的 `EventSource`。失败后有没有在 `onerror` 里无节制地重建连接，把名额占满。一个页面里仪表盘、铃铛、任务列表各开一条到同一主机的 SSE，单标签就可能先占掉好几条。

## 排查时可以做的（不做歪招）

- 标签隐藏或卸载时调用 `eventSource.close()`，避免后台页长期占着连接。
- 同页只保留一条到同端点的 SSE，多组件共用，而不是每个小组件各 new 一条。
- 看 Network 面板里连接是挂在 HTTP/1.1 还是 h2，以及服务器实际返回的 `Content-Type` 是不是 `text/event-stream`。
- 需要浏览器→服务器双向、或连接模型不同时，评估 WebSocket 等方案。那是换通道，不是「破解」EventSource 上限。

后端用 FastAPI `StreamingResponse` 推流、客户端取消怎样才断得干净，是另一条线（发布后可补互链）。前端这边先把连接生命周期和协议版本看清，再和后端对取消语义。不写绕过浏览器连接限制的技巧，也不建议用隐藏窗口、多域名裸分片之类办法硬扩。那些做法脆、难维护，还可能踩安全与隐私策略。上限是浏览器实现与规范现实，产品侧用共享连接、及时 `close`、以及部署侧的 HTTP/2 更靠谱。

你们线上 SSE 是 HTTP/1.1 还是已经上 h2？多标签出问题之前，单个标签里有没有重复创建 `EventSource`？
