## WebSocket 为什么要特殊处理
普通 HTTP 请求一问一答,连接用完就还回连接池;WebSocket 建立之后要长期占用连接双向收发。反向代理默认按短连接的思路工作,既不懂协议升级,也不习惯一个请求挂上几分钟,于是出现两种典型现象:握手阶段直接失败返回错误,或者连接建立后每隔几十秒莫名断开。问题多数不在后端服务,而在代理层少了几句交代。
## 三行配置的含义
在反向代理的 location 里加上这三行,绝大多数场景就够了:
nginx proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 300s;
第一行把客户端的 Upgrade 头原样传给后端,这是协议升级的开关,丢了它后端只会收到一个普通请求。第二行把 Connection 头改为 upgrade,告诉两端这条连接不再按普通请求的节奏管理。第三行把读超时拉长:代理默认读超时只有一分钟,聊天室、在线客服、行情推送这类连接只要空闲超过它就会被掐断,客户端表现就是周期性掉线重连。更稳妥的写法是配合 map 指令,根据请求头动态生成 Connection 的取值,让纯 HTTP 与 WebSocket 混跑的同一路径都正常工作。
## 配置后仍 502 的场景
按顺序查三处。一是后端监听地址:Nginx 与后端不在同一台机器时,后端要监听在对外可达的地址上,只绑回环地址等于无人接听。二是协议不匹配:后端以加密方式监听而代理仍按明文转发,握手阶段直接失败。三是超时链不一致:proxy_read_timeout 调大了,但后端框架自身的空闲断开时间更短,或者链路中间还有一层代理按自己的默认超时切连接,需要把整条链路的超时设置对齐,否则最短的那一层说了算。
## 验证方法
改完先 nginx -t 校验语法再 reload,随后用浏览器开发者工具的网络面板观察 WebSocket 帧是否持续收发,或者保持一条空闲连接记录断开时刻。断开时间点固定,基本就是某一层的超时在起作用,逐层比对间隔即可锁定。在顺云的云服务器上跑长连接业务时,记得同时关注连接数与内存水位,长连接积累的句柄开销比短连接高得多,配合监控告警提前扩容比事后救火从容。