云环境K8s集群WebSocket连接失败解决方案
云环境K8s集群WebSocket连接失败解决方案
一、问题描述
在云环境(如华为云)的K8s集群中部署WebSocket服务(Java后端+Vue前端+Python客户端)时,遇到**无法连接或握手失败(400 Bad Request)**问题,具体表现为:
- Python客户端日志显示:
Handshake status 400
; - Java后端日志无WebSocket连接记录;
- 浏览器开发者工具显示:WebSocket请求未升级为101状态(仍为HTTP 400)。
二、核心问题分析
WebSocket连接需要特殊的协议升级流程(从HTTP到WebSocket),而云环境中的Nginx-Ingress(K8s ingress controller)和**云负载均衡器(ELB)**默认未配置这些流程,导致:
- 协议头未传递:
Upgrade
和Connection
头未从客户端转发到后端服务; - 超时时间过短:Nginx-Ingress默认60秒超时,断开长连接;
- 跨域限制:后端服务未允许客户端的Origin(如
https://example.com
)。
三、分步解决方案
1. K8s Ingress配置:解决Nginx转发问题
需要的知识:
- Ingress是K8s的“智能路由”,本质是Nginx集群;
- WebSocket需要
Upgrade
和Connection
头传递。
修改ingress.yaml
:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: example-service-namenamespace: example-autoannotations:# 1. WebSocket必需:转发Upgrade和Connection头nginx.ingress.kubernetes.io/proxy-set-header: |Upgrade $http_upgrade;Connection $connection_upgrade;# 2. WebSocket必需:HTTP/1.1(之前已修正)nginx.ingress.kubernetes.io/proxy-http-version: "1.1"# 3. 超时设置(WebSocket长连接需要)nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"# 4. 路径重写:将/gcyiams/ws转发到Java服务的/ws端点(因context-path=/gcyiams,实际后端路径是/gcyiams/