io.vertx.core.impl.NoStackTraceThrowable连接已关闭异常的触发原因是什么?
这个io.vertx.core.impl.NoStackTraceThrowable: Connection is not active now, current status: CLOSED异常的核心本质是程序尝试在已经关闭的TCP连接上读写HTTP数据,偶发、和请求参数相关的特性刚好对应连接生命周期的边界场景,常见触发原因如下:
1. 长连接超时不匹配
- Vert.x默认开启HTTP长连接(keep-alive),请求会复用连接池中的TCP连接降低握手开销
- 如果上游客户端/负载均衡的连接闲置超时时间长于Vert.x服务端配置的
keepAliveTimeout,连接池取出的连接可能已经被服务端静默关闭,此时写入请求就会抛出异常 - 修改参数后复现概率变化的原因:不同参数对应的服务端处理耗时不同,刚好卡在连接闲置超时的临界值时就会偶发触发
2. 服务端连接状态异常
- 服务端GC停顿时间过长:GC期间服务端无法响应TCP心跳,操作系统或上游节点会主动断开连接,GC恢复后程序尝试往已关闭的连接写数据就会报错
- 跨线程共享连接对象:Vert.x的
HttpClient、HttpServerRequest、HttpServerResponse均非线程安全,若跨EventLoop线程共享同一个连接/请求对象,可能出现一个线程已经结束请求关闭连接,另一个线程还在尝试写入数据的情况 - 服务端负载突增:当日请求量上涨超过承载阈值时,Vert.x会主动回收部分闲置连接释放资源,刚好分配到刚回收的连接的请求就会触发异常
3. 中间链路主动断连
- 防火墙、网关等中间节点有独立的闲置连接回收策略,若连接闲置时间超过网关阈值,网关会主动断开两端的连接,此时客户端和服务端都未感知到连接状态变化,写入数据就会抛出异常
- 网络波动导致的偶发TCP断连,刚好在请求发送时触发
快速排查方案
- 开启Vert.x HttpClient的连接池日志,确认异常请求是否都命中了已标记为关闭的连接
- 对齐全链路的
keepAliveTimeout配置:保证Vert.x服务端的超时时间比上游所有节点的超时时间短5~10s,从根源避免上游拿到已关闭的连接 - 检查代码中是否有跨线程操作HTTP连接、请求/响应对象的逻辑,这类非线程安全对象只能在绑定的EventLoop线程中操作
内容的提问来源于stack exchange,提问作者RabbitNoTeeth
相关产品推荐
相关产品推荐

