本文目录
长连接容量不是“能连多少”,而是连接、消息、内存和恢复成本共同受控
先按在线连接、建连速率、上行与下行消息速率、单条大小、订阅扇出和断线恢复量建立负载模型,再分别限制单连接与单主题的发送队列。心跳只能帮助发现失效连接,不能证明业务消息已被处理;消息需要按业务选择可丢弃、可合并、必须确认或断线后补拉。客户端重连应使用退避与抖动,服务端发布需先停止接新连接、排空或转移现有连接,并为大规模断线保留握手和鉴权容量。验收必须覆盖慢消费者、代理空闲超时、弱网、实例退出和消息中间件故障,而不只是稳定网络下的连接数。
先按消息价值决定积压与恢复策略
| 消息类型 | 建议策略 | 错误处理的后果 |
|---|---|---|
| 状态快照 | 保留最新版本即可,队列拥堵时合并旧更新,重连后重新拉取权威状态 | 逐条补发已过期状态,客户端恢复时先处理大量无效消息 |
| 过程事件 | 使用稳定事件标识与游标,按保留窗口补拉,并允许接收方去重 | 只依赖内存连接,短暂断线就永久缺少关键事件 |
| 即时提示 | 明确允许丢弃的条件,必要时由普通接口提供未读摘要 | 把提示当可靠消息,用户误以为业务动作已完成 |
| 有副作用指令 | 通过可鉴权、幂等且可查询结果的业务接口执行,推送只通知状态变化 | 断线重发或多端在线导致重复执行支付、审批或设备控制 |
适用边界:实时体验不等于所有操作都走长连接
这份指南适合聊天、实时看板、协作状态、设备事件和 AI 流式输出等双向或服务端主动推送场景。低频通知、可轮询状态和普通提交仍可使用 HTTP;WebSocket 不会自动提供消息持久化、恰好一次处理或跨设备顺序。
先区分连接通道与权威业务状态。订单、审批、权限、计费和智能体工具执行应由可审计接口与持久化记录决定,长连接负责及时传递状态变化。客户端收到消息只代表数据到达应用,不等于用户已读或业务副作用已完成;需要确认时,应定义确认的是“收到”“展示”还是“处理成功”。
浏览器、小程序容器、原生 APP、反向代理和负载均衡对空闲连接、后台运行与网络切换的行为可能不同。不能把某个开发环境中的常驻连接假定为所有终端表现;上线前要在目标端、目标网络和实际代理链路验证。
- 为每类实时消息标明权威来源、可靠性和确认语义。
- 列出客户端、网关、负载均衡、应用和消息中间件的连接限制。
容量模型要同时计算在线连接与消息扇出
空闲连接主要占用文件描述符、套接字、TLS 状态和应用会话;活跃连接还消耗编码、加密、网络与发送队列。容量评估至少记录稳定在线数、每秒新建连接、消息到达率、单条大小、订阅人数和每条消息的实际投递副本。
一次主题更新向许多订阅者广播时,入口一条消息可能扩展为大量下行发送;只压测客户端上行 QPS 会遗漏主要成本。按连接分布到多个实例后,还要验证订阅路由和跨实例消息传递,不应让每个实例无条件接收所有租户的全部消息。连接数、业务在线人数和同时活跃发送数要分别报告。
建立握手与稳态两套容量结论。TLS、鉴权、订阅恢复和离线补拉集中发生时,建连路径可能先于消息路径饱和。容量余量需要覆盖实例故障或网络恢复时的集中回连,而不是只覆盖平稳时段。
- 记录连接数、建连率、上下行消息率、字节率、扇出和发送队列。
- 分别测空闲长连接、持续单播、高扇出广播和批量重连。
鉴权、心跳与关闭都要有明确状态机
握手时校验身份并不意味着连接可以永久使用原权限。账号停用、角色变化、令牌到期和租户切换需要可执行的续期或断开规则;服务端还应在每次订阅与敏感操作上校验当前授权,不能只相信客户端声明的频道。
RFC 6455 定义了 Ping、Pong 与 Close 控制帧:Ping 可用于保活或确认对端仍有响应,收到 Ping 的端点通常应尽快返回 Pong;正常关闭应使用关闭握手。心跳间隔和失效次数仍需结合代理空闲时间、移动端后台限制和业务恢复目标确定,没有通用秒数。应用层心跳若还携带登录态或版本,也要限制频率和大小。
检测到失效后及时释放订阅、内存队列和会话索引。滚动发布时先把实例从新建连接路由中摘除,向客户端表达计划关闭,再留出受控排空时间;强制终止应成为有指标的最后阶段,不能让客户端把正常发布误判成无限快速重连。
- 验证权限变更、令牌过期和主动踢出能影响已有连接。
- 记录关闭码、关闭原因、心跳往返、异常断开与资源释放时延。
慢消费者必须触发背压、合并或断开
服务端生成消息的速度可能长期高于某个客户端的接收速度。若每条连接都无限缓存,少量弱网设备就能持续占用内存;若发送线程被慢连接阻塞,其他正常连接也会受影响。每条连接、用户和主题都需要队列与字节上限。
WHATWG WebSockets 标准暴露 `bufferedAmount` 表示已经排队但尚未通过网络发送的数据量,并示例根据该值控制发送节奏;它说明客户端同样需要关注发送缓冲。服务端应采用自身运行库的可写状态或队列指标,不能假定调用 send 后对端已收到。达到上限时,根据消息语义丢弃旧快照、合并更新、暂停上游、降低频率或关闭连接。
必须可靠的事件不要无限塞进套接字队列,而应先写入可恢复存储,再用事件游标通知客户端补拉。对 AI 流式输出,可合并尚未发送的文本片段,并在取消后停止上游生成或工具工作;只关闭前端显示却让后台继续产生数据,会把慢消费者问题转成计算与费用浪费。
- 为队列条数、字节、最长等待和丢弃策略设置可观察上限。
- 验证单个慢客户端不会拖慢同实例的其他连接或阻塞消息消费。
重连要退避错峰,并从确定游标恢复
断线重连的目标不是越快越好,而是在恢复可用性的同时限制握手、鉴权和订阅放大。客户端应区分主动退出、鉴权失败、协议错误、网络切换和服务暂不可用;仅对可能恢复的情况使用有上限的退避与抖动。
重连后不要默认从内存中的最后界面继续。客户端携带已确认的事件游标或状态版本,服务端判断仍在保留窗口内就补发,否则返回需要重新同步并通过普通接口拉取最新快照。多端在线和重复补拉要求事件标识稳定,接收方可以去重;顺序只在明确的会话、主题或业务对象范围内保证。
实例同时重启、代理切换和运营商网络恢复会产生重连风暴。服务端要限制每个身份与来源的建连频率,为鉴权与补拉设置独立容量,并在过载时返回可识别的暂不可用结果。客户端不得立即循环创建连接,前端页面多开也应受账号或设备策略约束。
- 模拟大批连接同一时间断开,核对回连曲线和鉴权负载。
- 验证游标过期、消息重复、乱序与快照重同步不会破坏业务状态。
实施与验收:把稳态、故障和发布放在同一场景复测
实施先定义消息目录和可靠性,再打通连接鉴权、订阅索引、发送队列指标与关闭状态;随后从单播灰度到广播,最后加入断线恢复和滚动发布。每一步保留关闭新功能或退回普通查询的开关。
验收固定终端类型、代理链路、连接分布与消息模型,覆盖空闲连接、持续单播、高扇出、弱网慢消费者、客户端休眠、消息中间件暂停、实例退出和全量回连。除了连接成功率与消息延迟,还核对内存、文件描述符、队列字节、事件缺失和重复、鉴权失败、恢复时间及普通 HTTP 接口压力。
风险报告应说明没有覆盖的浏览器或小程序版本、消息保留窗口、允许丢弃的类型、最大恢复量和第三方网络限制。达到内存、队列或鉴权停止条件时主动降级或拒绝新连接,优先保护已经确认的业务操作;不能用“连接仍然建立”掩盖消息已延迟、被丢弃或无法恢复。
- 用业务事件清单核对不丢、可丢、可合并和需补拉的不同结果。
- 证明发布、故障与恢复期间连接资源可回收,消息最终状态可核对。
需求讨论中的问题
服务器能保持很多空闲连接,就说明 WebSocket 容量足够吗?
不能。还要测新建连接、鉴权、消息大小、广播扇出、慢消费者队列和故障后的重连。空闲连接测试只能说明部分连接资源,不能代表真实消息吞吐和恢复能力。
心跳收到 Pong,能否证明前一条业务消息已经处理?
不能。Ping/Pong 说明连接对端仍有响应,不代表业务消息已展示、持久化或完成。需要业务确认时,应定义稳定消息标识、确认阶段和结果查询。
断线后立即重连是不是用户体验最好?
单个用户可能更快,但大量客户端同时立即重连会压垮握手、鉴权和补拉链路。应按错误类型决定是否重连,使用退避与抖动,并让服务端具备过载保护和恢复容量。
WebSocket 可以保证消息不丢且只处理一次吗?
协议本身不提供这种业务保证。关键事件需要持久化、稳定标识、确认游标、补拉和去重;有副作用的操作还应通过幂等且可查询结果的业务接口执行。
WebSocket 长连接上线验收清单
可逐项勾选,辅助本次阅读;刷新页面后不保留。
参考资料
技术概念可进一步阅读以下资料;文中的业务场景与实施清单用于方案讨论。
- RFC 6455:The WebSocket Protocol
核验 WebSocket 数据与控制帧、Ping/Pong、关闭握手和关闭状态码等协议边界;心跳间隔、消息可靠性与重连策略仍由应用设计。
- WHATWG:WebSockets Standard
核验浏览器 WebSocket API 的发送、关闭与 bufferedAmount 语义;服务端队列阈值和业务恢复规则需按实现与场景验证。
需要评估现有系统的性能瓶颈?
提供关键业务路径、真实峰值、服务器与数据库配置,以及现有压测或故障记录,月弦科技可据此梳理优化顺序、实施范围和可验证的验收条件。