必须用map而非硬写Connection头,因普通HTTP请求也含Connection头(如keep-alive),硬设为upgrade会导致非WebSocket请求被误升级而返回400或断连;map通过判断$http_upgrade是否存在动态设为upgrade或close,精准匹配协议语义。

关键不是“升级头”,而是让 Nginx 准确识别并转发 WebSocket 握手所需的两个头部:Upgrade 和 Connection,且只在真正需要时才设为 upgrade。
为什么必须用 map 而不能直接写死 Connection 头
WebSocket 握手依赖客户端发送的 Upgrade: websocket 和 Connection: upgrade 两个头。但普通 HTTP 请求也带 Connection 头(比如 keep-alive 或 close)。如果在 location 里硬写:
proxy_set_header Connection "upgrade";
会导致所有请求都被标记为升级,后端对非 WebSocket 请求可能返回 400 或直接断连。
map 的作用是条件判断:只在 $http_upgrade 存在时设 Connection 为 upgrade,否则设为 close,完全匹配协议语义。
标准 map 配置写法(必须放在 http 块顶层)
复制到 nginx.conf 的 http { ... } 区域内,不能放在 server 或 location 里:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
说明:
- $http_upgrade 是 Nginx 自动提取的请求头值(如 websocket),空字符串 '' 表示该头未出现
- 只要 Upgrade 头存在(非空),$connection_upgrade 就被赋值为 upgrade
- 没带 Upgrade 头时,$connection_upgrade = close,保持普通 HTTP 行为
location 中必须配套的三要素
仅定义 map 不够,还需在对应 WebSocket 的 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 动态生成的值
这三者缺一不可,否则握手会失败或误影响其他请求。
别漏掉 WebSocket 长连接的关键调优项
WebSocket 是长连接,Nginx 默认配置会主动中断它:
- proxy_read_timeout 3600; —— 防止空闲连接被断开(按业务最长等待时间设)
- proxy_send_timeout 3600; —— 保障服务端推送不因超时中断
- proxy_buffering off; —— 关闭缓冲,避免消息堆积延迟
- proxy_cache_bypass $http_upgrade; —— 确保 Upgrade 请求绕过缓存
这些不参与头部升级逻辑,却是连接稳定运行的实际支撑。


















