Wildfly 8.2高事务量下突然停止接收连接问题排查求助
排查Wildfly 8.2高负载下停止接收入站连接的问题
这种情况我之前维护老版本Wildfly时碰到过好几次,从你描述的“堆内存只用了25%、服务器内存仅用4GB”来看,堆内存耗尽肯定不是根因,得从非堆资源、线程/连接池、系统限制或者版本bug这几个方向入手:
1. 非堆内存(Metaspace/PermGen)耗尽
Wildfly 8.2如果搭配Java 8,用的是Metaspace而非传统的PermGen;如果是Java 7及以下则是PermGen。这部分内存用来存储类元数据、字符串常量等,堆内存统计不会包含这部分:
- 如果没给Metaspace/PermGen设置上限,或者上限太小,高负载下大量动态生成的类(比如事务代理、热部署的类)会持续占用非堆内存,直到耗尽服务器剩余的2GB内存(你说服务器用了4GB,堆占1.5GB左右,剩下的2GB可能全被非堆占了)。
- 排查方法:
- 查看JVM启动参数里有没有
-XX:MaxMetaspaceSize(Java8+)或-XX:MaxPermSize,如果没有建议设置为256m或512m; - 查看JVM的gc.log,看非堆内存的增长趋势;
- 用
jstat -gcmetacapacity <pid>(Java8)或jstat -gcpermcapacity <pid>(Java7)查看非堆内存的使用情况。
- 查看JVM启动参数里有没有
2. 线程池/连接池耗尽
Wildfly的请求处理依赖Undertow的IO线程池、工作线程池,以及数据库连接池,任何一个池耗尽都会导致无法处理新连接:
- Undertow线程池:默认的IO线程数是CPU核心数,工作线程数是CPU核心数*8,如果你的服务器CPU核心少,高事务量下很快会占满所有线程;
- 数据库连接池:如果数据源的最大连接数设得太小,事务请求都在等待数据库连接,导致工作线程被阻塞,无法处理新的HTTP连接;
- 排查方法:
- 登录Wildfly管理控制台(默认
http://<server-ip>:9990),在「运行时」->「服务器」->「线程池」里查看io-threads、worker-threads的使用率; - 查看数据源的连接池状态,看是否达到最大连接数;
- 检查
server.log里有没有类似"No available worker threads"或"Connection pool exhausted"的报错。
- 登录Wildfly管理控制台(默认
3. 系统级资源限制
Linux系统对进程的文件句柄数、线程数有默认限制,高负载下很容易触发:
- 文件句柄限制:每个TCP连接都会占用一个文件句柄,默认的进程文件句柄上限可能只有1024,高负载下很快就会用完,导致无法创建新连接;
- 线程数限制:Linux对单个进程的线程数也有限制,线程池满了之后无法创建新线程处理请求;
- 排查方法:
- 用
ulimit -n查看当前Wildfly进程的文件句柄限制,建议在启动脚本里设置ulimit -n 65535; - 用
ps -Lf <pid>查看Wildfly的线程数,对比系统的线程限制(/proc/sys/kernel/threads-max); - 查看系统日志(
/var/log/messages或syslog),有没有"too many open files"的错误。
- 用
4. Wildfly 8.2的已知版本bug
Wildfly 8.2是比较老的版本(2015年发布),存在一些连接处理相关的bug:
- 比如Undertow的连接泄漏问题,当请求异常时连接没有正确释放,积累到一定数量后无法处理新连接;
- 或者线程池死锁的bug,导致线程无法被回收复用;
- 解决方法:升级到Wildfly 8系列的最新补丁版本(比如
8.2.1.Final),这个版本修复了不少高负载下的稳定性问题。
快速排查步骤
- 优先查看Wildfly的
server.log,找报错信息,这是最快定位根因的方法; - 用
jconsole或jvisualvm连接到Wildfly,实时监控非堆内存、线程池的状态; - 检查系统的资源限制,确保文件句柄和线程数足够;
- 尝试升级到Wildfly 8.2.1.Final,看问题是否复现。
内容的提问来源于stack exchange,提问作者GRTZ
相关产品推荐
相关产品推荐

