websocket连接在60秒左右断开,是因为ingress-nginx默认proxy-read-timeout和proxy-send-timeout均为60秒,该值指两次读/写操作间的最大空闲时间,而非连接总时长;若后端或客户端心跳间隔超过60秒(如设为30–45秒但偶有延迟),nginx即主动关闭连接,导致“websocket closed before established”等错误。

WebSocket在K8S中跑不稳,90%是因为Ingress层的超时没调对——proxy-read-timeout和proxy-send-timeout默认60秒,而真实业务里心跳间隔常设为30–45秒,一卡就断。
为什么WebSocket连接总在60秒左右断开
ingress-nginx原生支持WebSocket协议,但它的默认超时参数是为HTTP短连接设计的。只要后端1分钟内没发数据、或客户端1分钟内没发心跳,Nginx就会主动关闭连接,报错常见于客户端日志:WebSocketError: I/O failure 或浏览器控制台显示 WebSocket closed before the connection was established。
-
proxy-read-timeout:指Ingress从后端读取数据的**两次成功读操作之间的最大空闲时间**,不是整个连接存活时间 -
proxy-send-timeout:指Ingress向后端发送数据的**两次成功写操作之间的最大空闲时间** - 这两个值必须同时调大,且建议一致(如
"3600"),否则单边超时仍会触发断连 - 云厂商SLB(如阿里云CLB、AWS ALB)可能自带4分钟空闲超时,需同步检查并调整
必须加的Ingress注解和参数
仅靠nginx.ingress.kubernetes.io/proxy-read-timeout和nginx.ingress.kubernetes.io/proxy-send-timeout还不够。生产环境建议组合配置:
评估 Kubernetes 集群安全态势,覆盖 RBAC、工作负载安全、网络策略、基础设施即代码(IaC)、运行时监控和密钥管理等 30 项控制项……
-
nginx.ingress.kubernetes.io/proxy-http-version: "1.1":显式声明HTTP/1.1,确保Upgrade头不被降级 -
nginx.ingress.kubernetes.io/affinity: "cookie":多副本部署时防止连接漂移,避免因路由切换导致Upgrade失败 - 若服务监听路径非根路径(如
/ws),Ingresspath必须精确匹配,且pathType推荐用Exact而非Prefix,避免路径重写干扰Upgrade头 - 不要用
nginx.org/websocket-services——这是旧版NGINX Plus或kubernetes-ingress(非ingress-nginx)的注解,K8S社区版ingress-nginx不识别
跨域与TLS场景下的额外注意点
WebSocket走wss://时,TLS终止点必须在ingress-nginx层(即Ingress资源里配tls字段),不能让云LB直通TCP。否则SSL握手失败,客户端报ERR_SSL_PROTOCOL_ERROR。
- 启用CORS需单独加注解:
nginx.ingress.kubernetes.io/enable-cors: "true",否则前端new WebSocket("wss://...")可能被浏览器拦截 -
nginx.ingress.kubernetes.io/cors-allow-origin值设为"*"时,nginx.ingress.kubernetes.io/cors-allow-credentials必须为"false",否则浏览器拒绝连接 - 如果后端服务自己处理了
Origin校验,Ingress侧无需开启CORS,避免双重校验冲突
验证是否真正生效的实操步骤
改完Ingress YAML后,别急着测业务逻辑——先确认Nginx配置已落地:
- 进ingress-nginx Pod执行:
kubectl exec -n ingress-nginx deploy/ingress-nginx-controller -- cat /etc/nginx/nginx.conf | grep -A 5 -B 5 websocket,确认生成的server块里有proxy_http_version 1.1和proxy_set_header Upgrade $http_upgrade - 用
websocat直连Ingress暴露的域名:websocat wss://ws.example.com/ws --ping-interval=20,观察是否稳定运行超5分钟 - 查Ingress Controller日志:
kubectl logs -n ingress-nginx deploy/ingress-nginx-controller | grep -i "upgraded\|101",看到101 Switching Protocols才代表Upgrade成功 - 若仍断连,临时把
proxy-read-timeout设成"7200"再试——排除是不是后端心跳真的不达标
最易忽略的是IngressClass绑定和Controller版本兼容性:v1.2以下的ingress-nginx已停止维护,proxy-read-timeout等注解在v1.0中行为不稳定,务必确认kubectl get deploy -n ingress-nginx ingress-nginx-controller -o yaml里镜像tag ≥ v1.8.0。










