要让nginx的server块真正支持websocket反向代理,必须满足协议升级、连接保持和超时适配三条件:需配置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade",并设置proxy_read_timeout和proxy_send_timeout为较大值(如3600s),同时确保location路径精准匹配且不被其他规则截断。

要让 Nginx 的 server 块真正支持 WebSocket 反向代理,关键不是加个 proxy_pass 就完事,而是必须满足协议升级、连接保持和超时适配三个条件。配置写错一处,WebSocket 就会降级成普通 HTTP 请求,握手失败,前端报 Error during WebSocket handshake: Unexpected response code: 400/502。
WebSocket 必需的 server 块配置项
Nginx 的 server 块里,只要涉及 WebSocket 路径(比如 /ws/、/socket.io/ 或根路径 /),就必须包含以下核心指令:
proxy_http_version 1.1;
WebSocket 握手基于 HTTP/1.1,HTTP/1.0 不支持Upgrade头,必须显式指定。proxy_set_header Upgrade $http_upgrade;
把客户端发来的Upgrade: websocket头原样转发给后端。注意$http_upgrade是 Nginx 内置变量,大小写敏感,不能写成$upgrade或漏掉$。proxy_set_header Connection "upgrade";
显式设置Connection: upgrade,告诉后端这是协议升级请求。值必须是"upgrade"字符串(带英文双引号),不能是$connection_upgrade(那是 map 指令配合用的)或Upgrade。proxy_read_timeout和proxy_send_timeout需设为较大值
WebSocket 是长连接,空闲时不会频繁发 ping/pong。默认 60 秒超时极易断连。建议至少3600(1 小时),高实时场景可设86400(24 小时)。
location 路径匹配要精准
WebSocket 请求路径必须被明确匹配到,不能被其他 location 规则截断或重写:
- ✅ 推荐写法:
location /ws/ { ... }或location / { ... }(若整个服务走 WebSocket) - ❌ 避免写法:
location ~ \.php$ { ... }会优先匹配,导致/ws/被当成静态文件处理 - ❌ 错误写法:
location / { proxy_pass http://backend; }但没加 WebSocket 头——这只会代理普通 HTTP,不触发协议升级
常见易忽略的配套设置
proxy_set_header Host $host;
后端服务常依赖 Host 判断租户或路由,尤其多域名部署时不可省略。proxy_set_header X-Real-IP $remote_addr;和X-Forwarded-For $proxy_add_x_forwarded_for;
保证后端拿到真实客户端 IP,日志和限流才准确。proxy_buffering off;(可选)
若后端推送消息频率高、延迟敏感(如 noVNC、实时协作),关闭缓冲可减少延迟;但会增加 Nginx 内存压力,需权衡。
一个可用的最小完整示例
server {
listen 80;
server_name example.com;
location /ws/ {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 3600;
proxy_send_timeout 3600;
}
}
只要后端服务(如 Node.js 的 ws 库、Socket.IO、或 Python 的 websockets)监听在 127.0.0.1:3000 且路径为 /ws/,这个配置就能跑通 WebSocket 握手与通信。











