WebSocket连接60秒断开是因Nginx Ingress默认proxy_read_timeout和proxy_send_timeout均为60秒,需配置nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"、proxy-send-timeout: "3600"及Upgrade/Connection头透传。

WebSocket 在 Kubernetes 中无法直接走标准 Ingress HTTP 路由,必须显式启用长连接支持,否则连接会在 60 秒左右被 Nginx Ingress Controller 主动断开。
为什么 WebSocket 连接总在 60 秒后断开
这是 Nginx Ingress Controller 默认行为:HTTP 路由下,proxy_read_timeout 和 proxy_send_timeout 默认为 60 秒。WebSocket 握手虽走 HTTP Upgrade,但后续是全双工 TCP 流,超时机制仍生效。
- 即使客户端持续发 ping/pong,只要服务端响应延迟超过 60 秒,Nginx 就会关闭连接
- 错误现象常见为浏览器控制台报
WebSocket is closed before the connection is established或连接建立后随机中断 - 该问题与 TLS 终止位置无关(Ingress 终止或 Service Mesh 终止都会触发)
必须加的 Ingress 注解(Nginx Ingress Controller)
仅靠 ingress.kubernetes.io/ssl-passthrough: "true" 不够,需同时设置超时和协议升级头:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
-
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"—— 建议设为 3600(1 小时),避免频繁重连 -
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"—— 与 read 保持一致 nginx.ingress.kubernetes.io/configuration-snippet: |<br> proxy_set_header Upgrade $http_upgrade;<br> proxy_set_header Connection "upgrade";
—— 强制透传 Upgrade 头,否则 Nginx 不会触发 WebSocket 协议切换- 不要用
nginx.ingress.kubernetes.io/ssl-passthrough: "true"配合非 TLS 后端,会导致 502;passthrough 仅适用于后端自己处理 TLS 的场景
ALB Ingress 与 Nginx Ingress 的关键区别
阿里云 ALB Ingress(alb.ingress.kubernetes.io)原生支持 WebSocket,无需手动注入 Upgrade 头,但仍有超时限制:
- ALB 默认
idle_timeout是 60 秒,需通过alb.ingress.kubernetes.io/backend-protocol: "HTTP"+alb.ingress.kubernetes.io/idle-timeout: "3600"显式延长 - ALB 不支持
configuration-snippet类注解,Upgrade 行为由 ALB 控制面自动处理 - 若后端是 HTTPS(即 wss://),ALB 支持 TLS 终止,此时应设
alb.ingress.kubernetes.io/backend-protocol: "HTTPS",否则证书校验失败 - ALB 的
alb.ingress.kubernetes.io/conditions不影响 WebSocket,它只匹配请求阶段,而 WebSocket 升级发生在首请求中
ConfigMap 方式(TCP 层暴露)什么时候必须用
当你的服务不是基于 HTTP Upgrade 的标准 WebSocket(比如裸 TCP Socket、自定义二进制协议、gRPC-Web 等),Ingress 的七层能力就失效了,只能走四层透传:
- 必须在
ingress-nginxnamespace 下创建名为tcp-services的 ConfigMap,key 为宿主机端口(如8828),value 格式为namespace/service-name:port - 同时要确保
ingress-nginx-controllerDeployment 启动参数含--tcp-services-configmap=$(POD_NAMESPACE)/tcp-services - 该方式绕过所有 HTTP 层逻辑(包括 TLS 终止、路径路由、Header 修改),也意味着你无法用域名区分多个 WebSocket 服务,只能靠端口
- 注意:此方案要求集群节点有可访问的公网 IP,且防火墙放行对应端口;云厂商 SLB 可能不支持四层透传到 NodePort,需确认
真正容易被忽略的是:Ingress 注解只作用于对应 Ingress 资源所关联的 Service,如果 Service selector 错误导致无 Pod 被选中,即使注解全对,连接也会立即 502;建议先用 kubectl get endpoints -n <namespace><service-name></service-name></namespace> 确认 endpoints 非空再排查超时问题。

















