websocket限流需分三阶段:握手阶段用limit_req按ip限http请求,连接阶段用limit_conn控并发数,消息级限流必须由后端实现;nginx仅负责前两层兜底与监控。

WebSocket 连接在 Nginx 中默认不支持传统 HTTP 的限流机制(如 limit_req),因为其握手是 HTTP 升级请求,后续通信为长连接、无请求头复用。要实现有效的流量监控与限流,需结合协议特性分阶段处理:握手阶段用 HTTP 限流控制接入,数据传输阶段靠应用层或连接数维度管控,再辅以日志与指标采集。
握手阶段的请求限流(HTTP 层)
WebSocket 建立前需一次 GET 请求(含 Upgrade: websocket 头),Nginx 可对此类请求统一限流:
- 定义限流区域,按客户端 IP 或 Host 区分粒度:
limit_req_zone $binary_remote_addr zone=ws_limit:10m rate=5r/s; - 在 location 块中匹配 WebSocket 握手路径(如
/ws/或通配)并启用限流:location /ws/ {<br> limit_req zone=ws_limit burst=10 nodelay;<br> proxy_pass http://backend;<br> proxy_http_version 1.1;<br> proxy_set_header Upgrade $http_upgrade;<br> proxy_set_header Connection "upgrade";<br>} - 注意:
burst允许短时突发,nodelay避免排队延迟,适合低延迟要求的 WS 场景
连接数维度的全局或上游限流
单个用户可能建多个 WebSocket 连接,仅靠请求频次不够。Nginx Plus 支持 limit_conn,开源版可通过变量模拟粗粒度控制:
- 按客户端 IP 限制并发连接数:
limit_conn_zone $binary_remote_addr zone=conn_per_ip:10m;<br>limit_conn conn_per_ip 10;
- 若后端支持,可在 upstream 中配置
max_conns(需 Nginx 1.11.5+),防止压垮服务:upstream backend_ws {<br> server 10.0.0.1:8080 max_conns=100;<br>} - 配合
proxy_next_upstream off;避免重试导致连接数误增
基于日志的流量监控与分析
Nginx 默认日志不体现 WebSocket 特性,需定制 log_format 提取关键字段用于监控:
- 添加升级状态与连接时长:
log_format ws_log '$remote_addr - $remote_user [$time_local] '<br>'"$request" $status $body_bytes_sent '<br>'"$http_upgrade" "$connection_requests" $request_time;<br>access_log /var/log/nginx/ws_access.log ws_log;
- 重点字段说明:
–$http_upgrade为websocket表示握手成功
–$connection_requests统计该 TCP 连接上的请求数(对 WS 通常为 1)
–$request_time可反映握手耗时,异常值提示网络或后端问题 - 配合 Prometheus + nginx-vts-exporter 或自研脚本解析日志,统计每秒新建连接数、错误率、平均响应时间等指标
应用层协同限流(推荐补充方案)
Nginx 无法感知 WebSocket 消息内容与频率,真正细粒度限流(如每秒最多 20 条消息)必须由后端服务实现:
- 前端建立连接时携带 token 或 user_id,Nginx 透传至后端:
proxy_set_header X-User-ID $arg_uid;或提取 JWT - 后端基于用户 ID + 时间窗口(如 Redis + Lua)做消息级限流,返回 429 时 Nginx 可捕获并记录
- 利用 Nginx 的
auth_request模块,在握手前调用鉴权接口,该接口可同步完成速率检查
不复杂但容易忽略:WebSocket 限流不是“开个模块就生效”,得把握手、连接、消息三个层面拆开看,Nginx 负责前两层兜底和可观测性,真正的业务级控制还得靠后端配合。











