线上 java.lang.OutOfMemoryError: unable to create new native thread问题解决思路

问题来源:kafka多个topic的消费数据使用到了线程池的监听消费,以异步处理,提高效率。但是生产上代码运行一段时间后会报java.lang.OutOfMemoryError: unable to create new native thread 程序宕掉,是一个生产致命错误。

线程池配置如下:

 private static ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("thread-pool-kafka-capture-view").build();

 ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(9, Integer.MAX_VALUE, 1,
            TimeUnit.MINUTES, new ArrayBlockingQueue<>(30), threadFactory, new ThreadPoolExecutor.AbortPolicy());
threadPoolExecutor.execute(() -> {
   代码块
}

SpringBoot 的启动Jvm配置如下:

nohup java -server 
-Xms65536M 
-Xmx65536M 
-Xmn24576M 
-Xss1M 
-XX:MetaspaceSize=8192M 
-XX:MaxMetaspaceSize=8192M 
-XX:MaxTenuringThreshold=0 
-XX:SurvivorRatio=8  
-XX:CMSFullGCsBeforeCompaction=0 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:+UseParNewGC 
-XX:+UseConcMarkSweepGC 
-XX:+CMSClassUnloadingEnabled  -jar test.jar 
--server.port=8888 --spring.profiles.active=prod > seat.log  2>&1 &

分配的堆内存仅占用了服务器的四分之一,除了堆内存系统还有192g的运行内存可用,根据可创建线程(Number of threads)的计算,服务的线程资源远没有达到阈值。

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
MaxProcessMemory 指的是一个进程的最大内存
JVMMemory         JVM内存
ReservedOsMemory  保留的操作系统内存
ThreadStackSize      线程栈的大小

在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生 java.lang.OutOfMemoryError: unable to create new native thread。但是这里是使用的高性能服务器,且JVM最大内存仅占了四分之一,所以可以忽略不计,不必降低启动参数的最大堆内存大小,也不用考虑优化代码的线程创建,或是降低线程栈的大小。

于是解决问题的来源指向了操作系统线程数阈值的设置。

操作系统会限制进程允许创建的线程数,使用ulimit -u命令查看限制。某些服务器上此阈值设置的过小,比如1024。一旦应用创建超过1024个线程,就会遇到java.lang.OutOfMemoryError: unable to create new native thread问题。如果是这种情况,可以调大操作系统线程数阈值。

解决思路:

  • 用ulimit命令查看一下系统的对进程资源的控制
ulimit -a  

查的max user processes才1024

  • 修改/etc/security/limits.conf文件
* soft nproc 204800       #限制最多打开的软件数
* hard nproc 204800       #限制打开软件的最多进程数
* soft nofile 102400      #限制最多打开的文件数
* hard nofile 102400      #限制最多运行的进程数,一般设置为65535

改完生效!

你可能感兴趣的:(项目运维,运维,架构,分布式)