WebSocket经多层代理后连接异常断开,寻求技术解决方案
当前连接链路:client -> example.com/websocket -> cluster.com/wscluster -> service:port/service,结合给出的配置,从以下方向逐一排查:
1. 补充长连接超时配置
WebSocket属于长连接,默认Nginx代理的读/写超时时间较短(通常为60秒),空闲连接会被主动断开。当前全链路配置均未设置长连接超时参数,需补充:
- 对外服务器Nginx配置:
location /websocket { proxy_pass https://clusteringress/wscluster; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; # 添加长连接超时配置 proxy_read_timeout 86400s; proxy_send_timeout 86400s; }
- 集群内Nginx配置:
location /wscluster { proxy_pass http://service; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; # 添加长连接超时配置 proxy_read_timeout 86400s; proxy_send_timeout 86400s; }
- K8s Ingress添加超时注解:
metadata: annotations: nginx.ingress.kubernetes.io/proxy-read-timeout: "86400" nginx.ingress.kubernetes.io/proxy-send-timeout: "86400" # 保留原有注解 nginx.ingress.kubernetes.io/proxy-http-version: "1.1" nginx.ingress.kubernetes.io/configuration-snippet: | proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade";
2. 统一Connection请求头大小写
当前对外服务器配置中Connection头值为小写"upgrade",Ingress注解中为大写"Upgrade"。虽HTTP头不区分大小写,但部分代理服务器对大小写敏感,可能引发握手异常。全链路统一修改为大写"Upgrade",确保配置一致性。
3. 检查请求路径传递匹配
Ingress路径规则为/wscluster(/|$)(.*),集群内Nginx的proxy_pass指向http://service(不带URI后缀),会将完整请求路径/wscluster传递给后端,但后端实际监听路径为/service,可能导致路径不匹配,后端返回错误响应进而触发连接断开。
调整集群内Nginx的proxy_pass配置,将路径映射到后端的/service:
location /wscluster { proxy_pass http://service/service; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_read_timeout 86400s; proxy_send_timeout 86400s; }
或修改Ingress路径规则,确保最终请求路径匹配后端服务的/service。
4. 完善Ingress的WebSocket支持注解
K8s Nginx Ingress需显式指定支持WebSocket的服务,添加websocket-services注解:
metadata: annotations: nginx.ingress.kubernetes.io/websocket-services: "servicename" # 保留其他原有注解
该注解会让Ingress针对指定服务优化长连接处理逻辑。
5. 检查后端服务的WebSocket配置
确认后端服务:
- 正确处理WebSocket握手请求,返回
101 Switching Protocols响应 - 自身配置了足够的长连接超时时间,无主动断开空闲连接的逻辑
- 未因内存、CPU资源耗尽导致连接异常中断
6. 排查网络中间设备的超时限制
对外服务器到K8集群之间的防火墙、负载均衡器等中间设备可能存在空闲连接超时设置(例如部分云厂商负载均衡默认超时300-350秒),需将其调整为与Nginx代理一致的超时时间,或在客户端与后端之间配置WebSocket心跳(定期发送ping帧)保持连接活跃。
内容的提问来源于stack exchange,提问作者Nitul

