5月27日 22:12
Nginx 如何配置 WebSocket 代理?
Nginx 如何配置 WebSocket 代理?
WebSocket 建立在 HTTP/1.1 之上,通过 Upgrade 机制将 HTTP 连接升级为全双工长连接。Nginx 默认会清除 Upgrade 头,所以必须手动配置才能正确代理 WebSocket。
核心配置(三行必写)
nginxlocation /ws { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }
proxy_http_version 1.1:WebSocket 要求 HTTP/1.1,Nginx 默认用 1.0Upgrade $http_upgrade:转发客户端的协议升级请求Connection "upgrade":告知 Nginx 这不是普通 HTTP,需要保持升级状态
推荐用 map 管理 Connection 头
多 location 场景下,硬编码 "upgrade" 会导致非 WebSocket 请求也被标记。用 map 按需切换更安全:
nginxmap $http_upgrade $connection_upgrade { default upgrade; '' close; } server { location /ws { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } }
没有 Upgrade 头时走 close,普通请求不受影响。
超时:为什么连着连着就断了?
Nginx 的 proxy_read_timeout 默认 60 秒。WebSocket 是长连接,如果 60 秒内没有数据传输,Nginx 会主动断开。解决办法:
nginxproxy_read_timeout 3600s; # 1小时 proxy_send_timeout 3600s; proxy_connect_timeout 60s; # 建连超时保持短即可
按业务调,不是越大越好。过长超时意味着僵死连接不会被回收。
WSS(WebSocket over TLS)
在 SSL server 块里照加那三行即可,Nginx 负责 TLS 卸载,后端仍用 ws://:
nginxserver { listen 443 ssl; ssl_certificate /etc/nginx/ssl/cert.pem; ssl_certificate_key /etc/nginx/ssl/key.pem; location /ws { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } }
负载均衡要注意会话保持
WebSocket 是有状态长连接,轮询策略会导致重连时切到不同后端。必须用 ip_hash:
nginxupstream ws_backend { ip_hash; server 10.0.0.1:8080; server 10.0.0.2:8080; }
如果后端是无状态的(如用 Redis Pub/Sub 做消息同步),也可以用轮询。
追问:连接断开怎么排查?
- 查 Nginx error log,确认是否超时断开
- 检查
Upgrade/Connection头是否正确转发 - 确认
proxy_buffering off已设置,避免数据被缓冲 - 检查防火墙或 CDN 是否拦截长连接
- 用
curl -H "Upgrade: websocket"手动测试握手是否返回 101