WebSocket服务端压力限流需四层防护:Nginx按真实IP限并发连接;应用层为每连接配独立滑动窗口限速;帧级与消息体双重约束防大包攻击;广播阶段分桶、裁剪、合并与去重。

WebSocket 服务端压力限流不能只靠一层防护,必须分层落地:Nginx 入口做连接数硬闸,应用层对每个连接独立速率控制,再配合消息内容与传输层约束。前端任何限制都不可信,所有策略必须在服务端强制生效。
第一道防线:Nginx 层按真实 IP 限并发连接
Nginx 是最轻量、最前置的拦截点,能在 WebSocket 握手(HTTP Upgrade)阶段就拒绝超额请求,避免资源浪费到应用进程。
- 用
map提取真实客户端 IP,优先信任X-Forwarded-For或CF-Connecting-IP(若走 Cloudflare,需配置set_real_ip_from和real_ip_header防伪造) - 通过
limit_conn_zone建立每 IP 连接计数器,limit_conn限制单 IP 最大并发连接数(例如 5 个) - 注意:
limit_conn统计的是当前活跃长连接数,不是请求数,对已建立连接持续生效
第二道防线:应用层为每个连接配独立滑动窗口
连接建立后,攻击者可能用脚本高频发小消息(如每秒百条 ping),耗尽 CPU。此时必须为每个 websocket.Conn 分配专属计数器,避免全局共享导致误杀正常用户。
- 使用内存 LRU 或 Redis Sorted Set 实现滑动窗口(如 5 秒内最多 10 条消息)
- 超限时静默丢弃,不返回错误帧——防止被用于探测或放大攻击
- 记录日志但不暴露限流逻辑细节,避免给攻击者提供反馈
第三道防线:帧级与消息体双重约束
防大包攻击和内存溢出,需从协议底层设限。
- 设置最大帧大小(如 Java-WebSocket 的
maxFrameSize=2MB),超过直接抛LimitExceededException - 对分片消息做累积校验,防止绕过单帧限制(如连续帧总大小超限则清空缓冲并中断)
- 业务消息体严格 ≤64KB;超长内容必须拆块,带序号与 SHA256 摘要,由客户端拼接校验
第四道防线:广播与推送阶段做裁剪与合并
千万级连接下,全量遍历广播是性能杀手,必须在消息分发前过滤和聚合。
- 连接按
room_id % N分桶,每桶独占锁或读写锁,实现并发广播 - 广播前剔除超时未心跳的僵尸连接,跳过非目标角色(如游客不收管理指令)
- 同一毫秒窗口内发往同一连接的多条高频消息(如位置更新)合并为数组发送,降低帧数量级
- 对重复通知类消息(如“刷新页面”)用 Redis 设置 1 秒去重 Key,避免前端雪崩式重绘











