nginx代理websocket并发上不去主因是负载均衡层未透传upgrade和connection头,导致握手失败;必须配置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade",并调大proxy_read_timeout。

WebSocket 并发上不去,大概率不是后端代码或服务器性能问题,而是负载均衡层没正确透传协议升级请求,导致连接被降级成短轮询或直接中断。Nginx 代理、云厂商 LB 都必须显式支持 Upgrade 和 Connection: upgrade 头,否则 WebSocket 握手失败,客户端反复重连——看起来像“并发上不去”,实则是连接根本建不起来。
为什么阿里云/腾讯云 LB 默认不转发 WebSocket 升级头
传统四层(TCP)负载均衡器只做 IP+端口转发,不解析 HTTP 头,自然无法识别 Upgrade: websocket;七层(HTTP/HTTPS)负载均衡器虽能解析,但默认策略往往只处理普通 HTTP 请求,对非标准头(如 Upgrade)直接丢弃或忽略。
- 阿里云 ALB(应用型)默认支持 WebSocket,但需在监听配置中**显式开启“WebSocket 支持”开关**(2026年新版控制台已集成,旧版需手动勾选)
- 腾讯云 CLB 的七层 HTTPS 监听,必须在“高级配置”里启用
HTTP/2和WebSocket 透传,否则$http_upgrade变量为空,后端收不到升级信号 - 若误用四层 TCP 监听承载 WebSocket 流量,即使后端服务正常,客户端也会卡在
CONNECTING状态,Chrome DevTools Network 标签页里能看到大量pending的 ws:// 请求
Nginx 作为前置代理时的三个致命配置漏项
很多团队在云 LB 后再套一层 Nginx(比如统一 SSL 终结),结果 WebSocket 在这一层就断了。关键不是“配了没”,而是“配对没”:
-
proxy_http_version 1.1必须写死,不能依赖默认值(某些旧版本 Nginx 默认是 1.0) -
proxy_set_header Upgrade $http_upgrade中的$http_upgrade是 Nginx 内置变量,仅当原始请求含Upgrade头时才非空;若写成字面量"websocket",会导致非 WebSocket 请求也被强行升级,引发 400 错误 -
proxy_read_timeout建议设为300或更高,云 LB 自身也有空闲超时(如阿里云 ALB 默认 60s),若 Nginx 先断开,会触发onclose且错误码为1006(abnormal closure)
后端服务部署时的会话粘滞陷阱
WebSocket 连接是长生命周期的,如果负载均衡把同一用户的多次心跳请求打到不同后端节点,而你的会话状态(如用户 ID、鉴权 token)只存在内存里,就会出现“已登录却提示未授权”或消息收不到。
- 阿里云 ALB 支持
源 IP 一致性调度(即 ip_hash),但注意:它对 NAT 环境下的客户端不友好(所有用户 IP 都是同一个出口 IP) - 腾讯云 CLB 的
会话保持功能需开启并设置超时时间(建议 ≥ 3600s),且仅对七层监听生效;四层监听不支持 - 更稳妥的做法是后端改用 Redis 存储连接映射关系,此时可放心用轮询算法,避免单点压力集中
真正卡住 WebSocket 并发的,往往不是带宽或 CPU,而是某一层悄悄吞掉了 Upgrade 头,或者健康检查配置不当导致部分节点被踢出集群却没报警。上线前务必用 wscat -c wss://yourdomain.com/ws 直连验证握手状态,再查 Nginx access log 里是否有 101 Switching Protocols,最后看云厂商控制台的“当前连接数”监控是否与实际匹配——三者不一致,问题一定出在中间链路上。











