Jetty 9.4.38启动时Connector数量激增占满线程池启动失败问题咨询
根因分析
你遇到的Jetty无限创建Connector、线程不足的问题,在9.4.38版本中通常由以下两个场景触发:
- 启动逻辑无幂等校验:API触发Jetty启动的逻辑未做状态校验,高并发场景下同一个Server实例的启动方法被多次并行调用,每次调用都会生成新的ServerConnector实例并注册到Server上,即使显式设置了仅创建1个Connector,多次调用也会生成多份实例。
- 旧Connector未清理:启动逻辑中每次都新建ServerConnector,但未将之前已经注册到Server实例的Connector移除,也没有校验当前Server已有的Connector数量,导致冗余Connector持续累积。
每个Jetty ServerConnector默认会占用固定数量的线程(4核CPU默认配置为1个Acceptor线程+4个Selector线程,共5个线程),Connector数量越多占用的线程配额越多,超过QueuedThreadPool配置的最大线程数时,就会抛出你遇到的线程不足异常:
could not subscribe connector
java.lang.IllegalStateException: Insufficient configured threads: required=200 < max=200 for QueuedThreadPool[qtp370296980]@16124894{STARTED,8<=144<=200,i=0,r=-1,q=0}[ReservedThreadExecutor@3825f21{s=0/6,p=0}]
at org.eclipse.jetty.util.thread.ThreadPoolBudget.check(ThreadPoolBudget.java:165)
...
修复方案
- 新增启动逻辑幂等校验
启动前先判断Server的运行状态,如果已经处于启动中或已启动状态,直接返回,避免重复执行启动逻辑,参考实现如下:// 双重校验锁保证幂等 if (server.isStarting() || server.isRunning()) { return; } synchronized (jetServerLock) { if (server.isStarting() || server.isRunning()) { return; } // 原有启动逻辑 } - 注册Connector前清理冗余实例
每次添加Connector前先清空Server中已注册的所有Connector,避免冗余实例占用资源:// 清理旧Connector for (Connector connector : server.getConnectors()) { server.removeConnector(connector); connector.stop(); } // 注册新的单个Connector server.addConnector(customSingleConnector); - 可选:调大线程池配额
若业务场景确实需要多个Connector,可适当调大QueuedThreadPool的maxThreads参数,注意预留足够的业务处理线程配额。
验证方法
修复后在启动逻辑中新增日志,打印Server注册的Connector数量,确认启动完成后Connector数量始终为1即可。
内容的提问来源于stack exchange,提问作者defect_analyst
相关产品推荐
相关产品推荐

