nginx代理websocket必须显式配置:启用proxy_http_version 1.1、透传upgrade头($http_upgrade)、固定设置connection为"upgrade"或用map动态映射、关闭缓冲与缓存、大幅延长proxy_read_timeout和proxy_send_timeout。

Linux 下用 Nginx 代理 WebSocket,核心不是“支持与否”,而是“必须显式配置”。Nginx 1.3.13+ 原生支持,但默认配置完全不适用 WebSocket —— 握手会失败、连接几秒后静默断开,问题几乎都出在头透传和超时设置上。
必需的协议升级头配置
WebSocket 握手依赖 HTTP/1.1 的 Upgrade 机制,而 Nginx 默认丢弃逐跳(hop-by-hop)头,导致后端收不到 Upgrade: websocket 和 Connection: Upgrade。必须手动透传:
-
固定使用 HTTP/1.1:
proxy_http_version 1.1;(HTTP/1.0 不支持 Upgrade,会直接降级) -
Upgrade 头必须透传:
proxy_set_header Upgrade $http_upgrade; -
Connection 头不能靠变量:不能写
$http_connection(它常是keep-alive),必须设为字符串"upgrade";更稳妥的做法是配合map指令动态控制:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
然后在 location 中写:proxy_set_header Connection $connection_upgrade;——这样普通 HTTP 请求不会被误升级。
关闭缓冲与禁用缓存
WebSocket 是帧流式通信,Nginx 默认开启的缓冲和缓存会粘包、延迟甚至截断数据:
-
关闭响应缓冲:
proxy_buffering off; -
禁用代理缓存:
proxy_cache off; - 如果用了
proxy_cache_valid等指令,务必在 WebSocket location 中显式关闭
长连接超时必须调大
Nginx 默认的 60 秒空闲超时对 WebSocket 来说太短,心跳间隔稍长就会触发断连:
-
读取超时(服务端长时间没发数据):
proxy_read_timeout 86400;(建议设为 24 小时或按业务心跳周期 × 3) -
发送超时(客户端发帧后服务端迟迟不响应):
proxy_send_timeout 86400; -
连接建立超时(可保持默认或设为 30s):
proxy_connect_timeout 30s;
完整 location 示例(含 HTTPS 支持)
假设后端 WebSocket 服务运行在 localhost:8080,路径为 /ws/:
upstream ws_backend {
server 127.0.0.1:8080;
}
server {
listen 443 ssl http2;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
location /ws/ {
proxy_pass http://ws_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 86400;
proxy_send_timeout 86400;
proxy_connect_timeout 30s;
}
}
改完配置后执行 sudo nginx -t 测试语法,再 sudo systemctl reload nginx 生效。前端连接地址应为 wss://example.com/ws/(HTTPS 下必须用 wss)。











