WebSocket无内置流量控制,需手动实现:①发送队列+节流限频;②基于ACK的滑动窗口;③监听bufferedAmount被动节制;④结合服务端背压信号协同降速;⑤断连时清空队列。

WebSocket 本身不提供内置的流量控制机制,客户端的流量控制需要开发者手动实现,核心思路是:限制发送频率、缓冲未确认消息、结合服务端反馈(如 ACK)动态调整发送节奏。
使用发送队列 + 节流(Throttling)
避免高频 send() 调用压垮网络或服务端。适合消息突发但无需实时送达的场景。
- 维护一个待发送消息队列(如
Array或Queue类) - 用
setTimeout或setInterval控制每秒最多发 N 条(例如 10 条/秒) - 每次只从队列取一条发送,成功后才取下一条;失败时可重试或丢弃
- 示例:设置
maxRate = 10,用requestIdleCallback或时间戳判断是否达到发送窗口
基于服务端 ACK 的滑动窗口
更精确的控制方式,适用于要求可靠、有序、不超载的业务(如协同编辑、实时游戏)。
- 客户端每发一条消息,附带唯一序列号(
seqId)并暂存进待确认队列 - 服务端处理完后回传
{ type: 'ACK', seqId: 123 } - 客户端收到 ACK 后,从待确认队列中移除对应项,并允许继续发送新消息
- 设定最大未确认数(如
windowSize = 5),当待确认数 ≥ windowSize 时暂停发送
监听 bufferedAmount 做被动节制
WebSocket.bufferedAmount 返回当前已调用 send() 但尚未被底层协议发出的字节数(即内核发送缓冲区大小)。这是浏览器提供的关键指标。
立即学习“Java免费学习笔记(深入)”;
- 定期检查(如在
send()后或setInterval中):if (ws.bufferedAmount > 1024 * 64) { pauseSending = true; } - 配合
onopen和onclose重置状态,避免缓冲区持续堆积 - 注意:该值只反映已入队但未发出的数据,不包括应用层队列;需与自定义队列配合使用才完整
结合连接状态与背压信号
真实环境中,光靠客户端逻辑不够,需和服务端协同。服务端可在压力大时主动通知客户端降速。
- 约定协议字段,如服务端推送
{ type: 'BACKPRESSURE', level: 'high' } - 客户端收到后,自动将发送速率减半,或暂停 1–3 秒再恢复
- 可搭配指数退避(exponential backoff)策略,逐步试探恢复能力
- 断线重连时清空所有待发/待确认消息,防止旧消息洪峰冲击新连接


















