nginx反代websocket需配置三要素:透传upgrade和connection头、调大proxy_read_timeout、启用http/1.1并关闭缓冲;否则连接易断,报错1006或502。

Go服务跑在Nginx后面,WebSocket连接稳定不了——不是代码问题,是Nginx默认把长连接当短连接处理了。核心就三件事:头没透传、协议没升级、超时太短。
proxy_set_header Upgrade $http_upgrade 和 Connection "upgrade" 必须配对
Go的WebSocket库(比如gorilla/websocket)只认这两个请求头来触发协议升级。Nginx默认不转发它们,所以后端收不到 Upgrade: websocket 和 Connection: Upgrade,直接返回400或502。
-
proxy_set_header Upgrade $http_upgrade;把客户端带的Upgrade头原样传下去,值可能是websocket或空(比如刷新页面时) -
proxy_set_header Connection "upgrade";注意双引号——不加引号会被Nginx解析成变量$connection,结果传过去的是空值或乱码 - 这两行必须放在
location /ws/ { ... }块里,不能只写在server或http级别
proxy_read_timeout 必须显式设大,且 ≥ 前端心跳间隔
gorilla/websocket 默认心跳是 30 秒,但 Nginx 的 proxy_read_timeout 默认只有 60 秒。只要一次心跳延迟或网络抖动,Nginx 就会先关掉和 Go 后端的连接,导致前端报 close 1006 unexpected EOF。
- 设成
proxy_read_timeout 86400;(24 小时)最省心,比业务侧心跳逻辑更可靠 - 如果后端用了
websocket.DefaultWriteWait = 10 * time.Second这类设置,proxy_send_timeout也得同步调大,否则大消息发一半就被Nginx掐断 - 别信“设成0就无限等待”——Nginx不支持0,设了等于没设
proxy_http_version 1.1 和 proxy_buffering off 是保底项
HTTP/1.0 不支持 Upgrade,而 proxy_buffering on 会让Nginx缓存后端推送的数据,破坏WebSocket的流式特性。
- 加
proxy_http_version 1.1;虽然现代Nginx默认已是1.1,但显式声明能避免某些旧版本或定制编译环境出错 -
proxy_buffering off;关闭缓冲,防止Nginx攒着消息不往下推,尤其影响实时通知类场景 - 如果用了HTTPS反代,确认
server块里有完整SSL配置(证书、密钥、ssl_protocols TLSv1.2 TLSv1.3),否则浏览器拒绝建立wss://连接
最容易被忽略的是:Nginx错误日志里出现 upstream prematurely closed connection 时,很多人去查Go代码,其实该立刻去看 proxy_read_timeout 是否生效、以及 $http_upgrade 变量是否为空——这两个点卡住,其他配置再全也没用。











