You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Fusion服务器Jetty线程线性增长致OOM,求线程限制方案

解决Jetty线程线性增长导致OOM的问题

让我来帮你梳理下可能的原因和解决办法——我之前也碰到过类似的Jetty线程泄漏问题,相同配置不同服务器表现差异大,大概率是特定场景下的线程泄漏,而非单纯的配置不生效。

第一步:先确认你的线程池配置真的在生效

有时候start.ini的参数会被其他配置文件覆盖,别想当然认为设置了就生效:

  • 利用你已经启用的jmx模块,用jconsole或者jvisualvm连接服务器,找到org.eclipse.jetty.util.thread.ThreadPool这个MBean,查看实际的minThreads、maxThreads和idleTimeout是不是和你start.ini里的一致。
  • 检查有没有其他XML配置文件(比如etc/jetty.xml或者自定义的配置)里定义了QueuedThreadPool,如果有,这些XML的配置优先级可能比start.ini更高,会覆盖你的参数。

第二步:排查线程泄漏的核心原因

线程线性增长到上限,基本都是线程泄漏——正常情况下Jetty的线程池会复用线程,空闲超时后会销毁到minThreads数量。你需要找出哪些线程在不断创建却没被回收:

  • 用jstack <PID>导出线程栈,或者直接用New Relic的线程快照功能,查看大量增长的线程的栈信息:
    • 看看是不是有大量线程卡在阻塞状态:比如等待数据库连接池、外部API响应,或者某个锁没有释放?这种情况会导致线程一直被占用,池子里不得不创建新线程。
    • 检查有没有ThreadLocal未清理:如果业务代码里用了ThreadLocal但在请求结束后没移除,会导致线程被持有无法回收,时间长了就会堆积。
    • 确认异步请求处理逻辑:如果你用了AsyncContext(比如Servlet 3.0异步),有没有在处理完成后调用complete()?如果没调用,Jetty会一直持有这个线程不放。
  • 对比正常服务器和出问题服务器的流量、请求类型:是不是有特定的接口或者请求触发了线程泄漏?比如某个新上线的接口、大流量的请求类型。

第三步:确保线程池配置正确生效(如果确认配置被覆盖)

如果发现start.ini的参数没生效,可以直接在etc/jetty.xml里硬编码线程池配置,优先级更高:

<Set name="threadPool">
  <New class="org.eclipse.jetty.util.thread.QueuedThreadPool">
    <Set name="minThreads">10</Set>
    <Set name="maxThreads">150</Set>
    <Set name="idleTimeout">5000</Set>
    <Set name="detailedDump">true</Set> <!-- 开启详细线程dump,方便调试 -->
  </New>
</Set>

另外,检查你启用的模块有没有影响线程池:比如continuation模块是用来支持异步处理的,如果异步逻辑有问题,也会导致线程无法释放。

第四步:开启更详细的调试辅助

  • 在start.ini里添加jetty.threadPool.detailedDump=true,这样当你dump线程的时候,能看到每个线程处理的请求路径、状态,更容易定位泄漏点。
  • 利用New Relic的线程分析功能,查看线程的创建来源,有没有重复创建的自定义线程组,或者异常的线程生命周期。

第五步:排查第三方组件的问题

有时候线程泄漏不是Jetty本身的问题,而是依赖的第三方库导致的:

  • 检查有没有使用的客户端(比如Apache HTTP Client、Redis客户端)创建了自己的线程池,却没有正确关闭?比如有些客户端默认会创建后台线程,如果你每次请求都新建客户端实例,就会导致线程堆积。
  • 对比正常服务器和出问题服务器的依赖版本:是不是某个组件版本不一致,引入了线程泄漏的bug?

内容的提问来源于stack exchange,提问作者Nishkarsh Dixit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 08:18:14