全栈视角下的实时通信:一次多设备在线问题的复盘

test12026-09-118 次阅读

最近在做一个 IM 类的全栈项目,前端 React、后端 Go,实时通道走 WebSocket。功能跑通后,本地开发一切正常,一上生产环境就出怪事:用户同时开三四个标签页,只有前两个能加载出来,后面的页面一直转圈,刷新也没用。

现象与排查

第一反应是前端状态管理写错了,或者 WebSocket 重连逻辑有 bug。但奇怪的是,单个标签页完全正常,数量一多才出问题。后来用浏览器开发者工具抓网络,发现卡住的不是业务接口,而是连 WebSocket 握手都排不上队。

根因:被忽略的连接数限制

浏览器对同一个域的 HTTP/1.1 并发连接数有上限(常见是 6 个)。更要命的是,开发者工具开着的时候,它本身会占用一条持久连接。也就是说,留给业务的长连接名额比你想的更少。标签页一多,新的 WebSocket 握手就只能排队,于是页面卡在加载。

为什么本地 dev 不容易复现?因为 npm run devnpm run preview 在连接复用、协议版本上的行为并不完全一致。很多只在生产环境暴露的问题,其实是被 dev 模式"掩盖"了。结论很朴素:上线前一定要用 preview 或真实部署环境复现一遍。

多设备在线状态怎么建模

另一个相关的问题是"在线状态"。简单的在线/离线已经不够用了,用户可能同时用 Web、桌面端、手机在线。正确的做法是:在 WebSocket 握手和心跳里带上 device 字段,服务端按 connection 维度聚合,而不是按用户维度粗暴地设一个在线标志。

这样多端才会互不踢下线,管理后台也能展示"Web / Desktop / iOS"这样的设备级图标,而不是一个笼统的绿点。

小结

实时通信的坑,往往不在协议本身,而在"浏览器约束 + 环境差异 + 状态建模"这三者的交界处。排查时先问自己三个问题:连接数够不够?dev 和生产一致吗?状态是按连接还是按用户聚合的?想清楚这三点,大部分多设备问题都能定位。

T

test1

文章作者

最近在做一个 IM 类的全栈项目,前端 React、后端 Go,实时通道走 WebSocket。功能跑通后,本地开发一切...

分类
技术
发布时间
2026-09-11
字数
约 832 字
阅读
8 次