关键在于用map指令动态设置Connection头:当$http_upgrade存在时设为upgrade,为空时设为close,并配合proxy_http_version 1.1、proxy_set_header Upgrade $http_upgrade和proxy_set_header Connection $connection_upgrade三要素,确保仅WebSocket请求升级、普通HTTP请求不误触发。

要让Nginx正确代理WebSocket,关键不是强行把所有请求都标为升级,而是只在客户端真发起Upgrade请求时才触发协议切换——map指令正是实现这种“按需升级”的核心机制。
为什么必须用 map 而不能硬写 Connection: upgrade
WebSocket握手依赖两个头协同工作:Upgrade: websocket 和 Connection: upgrade。但普通HTTP请求也会带Connection头(比如keep-alive或close)。如果直接在location里写:
会导致所有请求都被后端当成升级请求处理,非WebSocket接口可能返回400或直接断连。
map的作用是:只在$http_upgrade存在时设为upgrade,为空时设为close,完全贴合协议语义。
map 的标准写法与生效位置
这段配置必须放在http块顶层(不能塞进server或location里):
default upgrade;
'' close;
}
-
$http_upgrade是Nginx自动提取的请求头值(如websocket) - 只要该头非空,
$connection_upgrade就赋值为upgrade - 如果请求没带Upgrade头(值为空字符串),就赋值为
close
location 中必须配套的三要素
仅定义map不够,对应location里必须同时启用以下三项(缺一不可):
-
proxy_http_version 1.1;—— HTTP/1.0不支持Upgrade,必须显式启用1.1 -
proxy_set_header Upgrade $http_upgrade;—— 原样透传原始Upgrade头 -
proxy_set_header Connection $connection_upgrade;—— 使用map生成的动态值
这三行顺序无关,但必须共存于同一location块中,才能完成一次干净的协议识别与转发。
别漏掉支撑长连接的关键调优项
WebSocket是长连接,Nginx默认超时和缓冲策略会破坏它:
-
proxy_read_timeout 3600;—— 防止空闲连接被主动断开 -
proxy_send_timeout 3600;—— 保障服务端推送不因超时中断 -
proxy_buffering off;—— 关闭缓冲,避免消息堆积延迟 -
proxy_cache_bypass $http_upgrade;—— 确保Upgrade请求绕过缓存
这些设置不参与头部动态升级,却是WebSocket稳定运行的实际基础。











