NGINX Websocket代理握手后立即关闭,无法维持连接求助
我之前碰到过几乎一模一样的情况,握手成功后立刻断开,大概率是NGINX没正确处理Websocket的升级逻辑,或者后端服务在握手完成后主动关闭了连接。给你几个一步步排查的方向:
1. 补全NGINX的Websocket核心配置
你的nginx.conf里http块内容没写完,但Websocket代理最关键的就是升级请求头的传递——如果缺少这些配置,NGINX不会把HTTP请求升级为Websocket连接,握手后自然会断开。在对应的location块里必须加上这些:
location /你的websocket路径/ { proxy_pass http://你的后端服务地址; # 比如http://localhost:8080 proxy_http_version 1.1; # 强制使用HTTP/1.1,Websocket依赖该版本协议 proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # 这两个头是触发Websocket升级的核心 # 额外必要头,确保后端能正确识别请求来源 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
如果之前的配置里没这些,先加上重启NGINX试试,这是最常见的触发原因。
2. 排查后端服务的握手响应
有时候问题不在NGINX,是后端服务在收到握手请求后,虽然返回了101状态码,但立刻关闭了连接。你可以用curl手动模拟握手请求,直接测试后端:
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Sec-WebSocket-Version: 13" -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" http://你的后端服务地址/websocket路径/
如果返回HTTP/1.1 101 Switching Protocols,但连接瞬间断开,那肯定是后端服务的问题——比如Websocket服务没正确启动,或者业务逻辑里有主动关闭连接的代码,得去查后端的运行日志。
3. 调整NGINX的缓冲区和超时设置
你说超时设置没用,可能是配置的位置不对——超时和缓冲区设置要放在对应的location块里,而不是全局http块:
location /你的websocket路径/ { # 上面的升级配置... proxy_buffering off; # 关闭缓冲区,Websocket是实时流,缓冲会导致异常断开 proxy_connect_timeout 7d; proxy_send_timeout 7d; proxy_read_timeout 7d; # 把超时设长,彻底排除超时断开的可能 }
proxy_buffering是很容易被忽略的点,开启的话NGINX会缓冲后端的响应,对Websocket这种长连接不友好,关闭后会直接转发消息。
4. 开启NGINX debug日志找细节
既然错误日志没信息,把日志级别改成debug,能看到握手过程的所有细节:
error_log /var/log/nginx/error.log debug;
重启NGINX后再测试连接,查看error.log,里面会显示请求头的传递、后端的响应状态、连接断开的具体原因,比如是NGINX主动断开还是后端触发的。
5. 检查中间设备的拦截
如果NGINX和前端之间有CDN、负载均衡,或者和后端之间有防火墙,这些设备可能没开启Websocket支持,或者拦截了长连接。比如有些CDN需要手动开启Websocket的转发规则,防火墙要允许长连接的保持。
内容的提问来源于stack exchange,提问作者Nicky

