Nginx代理WebSocket需三项升级动作(proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade、proxy_set_header Connection "upgrade")和两项保活控制(proxy_buffering off、proxy_read_timeout足够大),且必须置于精确匹配的location块中。

要在 Nginx 的 location 块中正确代理 WebSocket 并保持长连接,关键不是堆参数,而是精准满足协议升级与连接保活的底层要求——三项升级动作必须写全,两项保活控制必须到位,且全部放在匹配路径明确的 location 里,不能塞进根路径或全局配置。
必须透传 Upgrade 和 Connection 头
WebSocket 握手依赖 HTTP/1.1 的协议升级机制,Nginx 默认会丢弃这两个逐跳头,导致后端收不到信号、返回 200 而非 101,连接直接失败:
-
强制使用 HTTP/1.1:加
proxy_http_version 1.1;,HTTP/1.0 不支持 Upgrade,缺了这句握手必断 -
原样转发 Upgrade 头:用
proxy_set_header Upgrade $http_upgrade;,变量能兼容 websocket / mqtt / stomp 等多种客户端,比硬编码更健壮 -
显式声明协议切换意图:写
proxy_set_header Connection "upgrade";,注意是带英文双引号的字面量"upgrade",不是$http_connection(它常为keep-alive,会掩盖升级意图)
必须关闭缓冲并延长超时
WebSocket 是连续帧流(TEXT/BINARY/PING/PONG),Nginx 默认的缓冲和短超时会截断、延迟甚至误杀连接:
-
禁用响应缓冲:在 location 内加
proxy_buffering off;,防止多帧被攒批发出造成粘包或卡顿 -
显式禁用缓存:加
proxy_cache off;,避免 Upgrade 请求被缓存命中后返回 200 -
读超时设为远大于心跳间隔:如
proxy_read_timeout 86400;(24 小时),若后端心跳为 30 秒,至少设为 90 秒以上才安全 -
同步调大发送超时:加
proxy_send_timeout 86400;,防止后端推送广播消息、音频分片或慢响应时被中断
路径要精确匹配,避免混用或兜底
WebSocket 流量必须走专用路径,否则容易被其他规则干扰或误匹配:
- 用前缀匹配,例如
location /ws/ { ... }或location = /ws { ... },确保前端new WebSocket("wss://domain.com/ws")中的路径完全一致 - 不要放在
location / { ... }这类兜底块里,否则静态资源、API 接口可能意外触发 WebSocket 配置,引发冲突 - 可加简单校验增强健壮性:
if ($http_upgrade != "websocket") { return 403; },拦截非法请求
HTTPS 场景下需补充透传信息
若前端用 wss://,Nginx 终止 SSL 后,需让后端感知原始协议和客户端真实 IP:
- 在 server 块的 443 端口配置中,确保已设置
ssl_certificate和ssl_certificate_key - 添加
proxy_set_header X-Forwarded-Proto $scheme;,方便后端识别 HTTPS - 添加
proxy_set_header X-Real-IP $remote_addr;和proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; -
proxy_pass目标仍用http://backend,Nginx 解密后以 HTTP 转发给后端,不要写成https://











