Nginx反向代理websocket完整配置
Nginx 反向代理 WebSocket 时,如果只按普通 HTTP 代理配置,客户端连接很快会断开,或者直接返回 400、502 等错误。
核心原因有两个:Nginx 默认不会向 WebSocket 服务传递 Upgrade 和 Connection 头,同时 proxy_read_timeout 默认只有 60 秒,长连接一旦超过这个时间就会被 Nginx 切断。
本文给出可直接落地的完整配置,同时解决 ws/wss 反向代理和连接超时问题,适合尚未配置过 WebSocket 代理的新手运维参考。
准备工作:确认环境与源服务
先确认三件事:
- Nginx 版本:1.3 及以上版本才支持 WebSocket 反向代理,建议使用 1.18 或更新版本。执行
nginx -v查看。 - WebSocket 源服务地址:例如本地服务监听
127.0.0.1:8080,路径为/ws。 - 域名和证书:如果希望浏览器通过
wss://访问,需要提前配置 SSL 证书;只在内网测试可用ws://。
确认后,先备份原配置:cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak。
核心配置:普通 ws 反向代理
进入 Nginx 站点配置目录(如 /etc/nginx/conf.d/),新建一个配置文件或修改现有站点配置。
下面是一段最基础的 ws 反向代理配置:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name example.com;
location /ws {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
关键点说明:
proxy_set_header Upgrade $http_upgrade;和proxy_set_header Connection $connection_upgrade;是让 Nginx 正确转发 WebSocket 握手升级的必备条件。map块需要放在http上下文中,如果写在 server 里会报错。- 超时时间:
proxy_read_timeout控制从后端服务读取数据的等待时间,WebSocket 长连接建议设置为3600s,否则连接会在 60 秒后被动断开。同理也设置proxy_send_timeout。
配置完成后测试语法并重载:
nginx -t
systemctl reload nginx
如果 nginx -t 通过,说明配置格式正确。
升级为 wss:让加密 WebSocket 生效
当浏览器需要访问 wss://example.com/ws 时,Nginx 负责终止 TLS 加密,再以普通 ws:// 转发给后端。
只需要在原 server 上添加 SSL 监听,或新建一个 443 端口 server 块:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.crt;
ssl_certificate_key /etc/nginx/ssl/example.key;
location /ws {
proxy_pass http://127.0.0.1:8080;
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_read_timeout 3600s;
proxy_send_timeout 3600s;
}
}
需要留意:后端服务不变,仍然是 ws://,不要改成 proxy_pass https://,否则后端不认 TLS 就会握手失败。
证书路径根据你实际部署位置修改。
避坑:连接超时和不稳定的常见原因
实际使用中,不少连接问题不是 Nginx 配置写错,而是下面几个细节被忽略:
- 忘记配置
proxy_set_header Upgrade:最常见的 400 Bad Request 或 502 错误来源。可用curl -v -H "Connection: Upgrade" -H "Upgrade: websocket" http://127.0.0.1:8080/ws测试后端是否正常。 proxy_read_timeout太小:业务允许长连接时,如果一直周期性断开,先检查这里的值。日志中会出现upstream timed out的提示。- 多个 location 共用超时配置:如果项目里还有 API 接口,建议把 WebSocket 路径单独拆分出来,避免把上传文件接口的超时时间也拉到 3600 秒。
- 负载均衡多台后端:WebSocket 长连接必须绑定固定后端,否则握手成功后请求被转发到不维护连接的另一台机器。可使用
ip_hash或sticky模块,保证同一客户端始终访问同一后端。
验证配置是否真正生效
nginx -t 通过并不代表 WebSocket 代理成功,还需要实际连接测试。
- 使用浏览器开发者工具:打开 Console,执行
var ws = new WebSocket("ws://example.com/ws");
ws.onopen = function(){ console.log("connected"); };
ws.onclose = function(e){ console.log("closed", e.code, e.reason); };
- 使用命令行工具 wscat(Node 环境):
npm install -g wscat
wscat -c ws://example.com/ws
如果能正常收到 connected,说明代理成功。
然后把服务保持连接超过 60 秒,观察是否会断开;
若仍断开,重新检查 proxy_read_timeout 和 proxy_send_timeout 是否已加载。
- 查看 Nginx 错误日志:默认在
/var/log/nginx/error.log,出现upstream timed out时优先检查超时配置;出现no live upstreams时检查后端 WebSocket 服务是否存活。
完成以上步骤后,ws/wss 反向代理和连接超时问题基本都能解决。
如果之后遇到更复杂的场景,比如多站点共用 Nginx 或 TLS 证书更新,可以继续查阅本站其他运维教程。