Spring Boot集成Undertow服务无响应问题排查求助
问题分析:Spring Boot集成Undertow后XNIO I/O线程CPU占满导致服务无响应
问题概述
- 环境配置:Spring Boot v2.7.4 + Undertow v2.2.22.Final,基于Java 11(11.0.18_10-jdk-focal)镜像部署在Docker中
- 异常现象:服务运行一段时间后对HTTP请求无响应,执行
top -H -p <PID>命令可见XNIO-1 I/O-3、XNIO-1 I/O-1等线程CPU占用接近100% - 已尝试无效方案:添加
-Djdk.tls.acknowledgeCloseNotify=true参数、禁用TLSv1.3、降级JDK至11.0.16 - 关联线索:已定位到UNDERTOW-2239问题与当前现象高度匹配,准备升级Undertow至2.2.24.Final
Undertow自定义配置代码:
@Configuration class ServerConfiguration { @Bean fun embeddedServletContainerFactory(): UndertowServletWebServerFactory { val factory = UndertowServletWebServerFactory() factory.addBuilderCustomizers(UndertowBuilderCustomizer { builder -> builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true) }) return factory } }
已通过VisualVM捕获到问题发生时的监控数据及线程状态。
线程CPU占满的核心原因
UNDERTOW-2239是Undertow在HTTP/2协议处理逻辑中的无限循环bug,触发场景如下:
当客户端发送的HTTP/2帧存在异常(比如帧长度不符合规范、连接异常中断时的残留帧),Undertow的HTTP/2帧解析器会进入无限循环状态,持续占用CPU资源,导致I/O线程无法处理正常请求,最终使服务失去响应。
具体到Undertow 2.2.22.Final版本,在处理CONTINUATION帧或其他类型帧时,若帧长度计算出现偏差,会导致解析器反复尝试读取无效的帧数据,陷入死循环,直接耗尽I/O线程的CPU。
之前尝试方案无效的原因
-Djdk.tls.acknowledgeCloseNotify=true:该参数用于修复TLS连接关闭时的通知逻辑,与HTTP/2帧解析的无限循环问题无关- 禁用TLSv1.3:问题根源在Undertow的HTTP/2处理代码,并非TLS协议版本导致
- 降级JDK:此bug是Undertow的代码逻辑缺陷,与Java 11.x范围内的版本无关
验证与解决方案
- bug匹配验证:查看VisualVM导出的线程栈,若发现XNIO I/O线程卡在
io.undertow.protocols.http2.Http2FrameParser相关方法(如processFrame、readFrameData等循环逻辑)中,即可确认是UNDERTOW-2239导致的问题。 - 修复方案:升级Undertow至2.2.24.Final版本,该版本已修复UNDERTOW-2239的无限循环bug。由于Spring Boot 2.7.4默认依赖Undertow 2.2.22.Final,需显式指定版本:
- Maven配置:
<dependencyManagement> <dependencies> <dependency> <groupId>io.undertow</groupId> <artifactId>undertow-core</artifactId> <version>2.2.24.Final</version> </dependency> <dependency> <groupId>io.undertow</groupId> <artifactId>undertow-servlet</artifactId> <version>2.2.24.Final</version> </dependency> </dependencies> </dependencyManagement> - Gradle Kotlin DSL配置:
dependencyManagement { imports { mavenBom("io.undertow:undertow-bom:2.2.24.Final") } }
- Maven配置:
内容的提问来源于stack exchange,提问作者Forge_7
相关产品推荐
相关产品推荐

