SpringBoot+Tomcat部署K8s时WebSocket因Upgrade header为null握手失败
故障现象
服务端日志间歇性输出如下错误,非全量请求触发,已排除链路代理组件影响,应用部署于Kubernetes集群:
04:42:53.259 [41] [http-nio-8080-exec-8] ERROR org.springframework.web.socket.server.support.DefaultHandshakeHandler - Handshake failed due to invalid Upgrade header: null
非代理因素根因排查方向
- K8s Service会话亲和性未配置
WebSocket握手阶段需要同一客户端的多次协商请求落到同一个Pod实例,若Service未配置sessionAffinity: ClientIP,升级请求可能被负载均衡转发到未持有初始握手上下文的其他Pod,该Pod收到的请求无有效Upgrade头就会抛错,这类问题的典型特征就是偶发,和请求调度时机直接相关。 - 非标准请求访问WebSocket端点
K8s kubelet存活/就绪探针、集群内巡检组件、网络爬虫等请求不会携带Upgrade: websocket、Connection: Upgrade标准WebSocket握手头,直接访问WS端点时就会触发该错误。可匹配报错请求的来源IP、User-Agent先做排查,这类请求不属于正常业务请求,可通过拦截器过滤或调整探针探测路径规避。 - 节点网络/容器运行时偶发异常
低版本CNI插件(如Calico、Flannel)、容器运行时(如containerd)在节点网络吞吐过高、TCP连接数打满的场景下,会偶发出现TCP包重组失败、请求头截断的问题,导致服务端解析到的Upgrade字段为空。可核对报错时间点对应Pod所在节点的网络负载、运行时日志确认。 - 内嵌Tomcat连接资源耗尽
Spring Boot默认内嵌的Tomcat如果工作线程池、最大连接数配置不足,高并发场景下连接被打满时会出现请求不完整解析的问题,部分请求头字段会被置空。可关联报错时间点的Tomcat线程池监控、连接数指标确认,适当调大server.tomcat.max-threads、server.tomcat.max-connections参数验证。 - 客户端异常断开导致的不完整请求
浏览器页面卸载、客户端网络切换、SDK异常退出场景下,会出现TCP连接半关闭就发握手请求的情况,服务端无法读取到完整的请求头,就会判定Upgrade头为空。这类属于正常的无效连接场景,不影响正常业务,可通过自定义握手拦截器过滤这类请求,调低对应日志级别减少干扰。
内容的提问来源于stack exchange,提问作者pacman
相关产品推荐
相关产品推荐

