centos7 tomcat_CentOS7下Tomcat应用容器抛出Too many open files问题

背景

在实际开发中有一款设备管理软件,一般情况下接入的设备并不多,最多几十台;最近有一个项目中,需要接入2000台这样的设备,运行一段时间后,会大量抛出Too many open files;导致设备无法正常使用,重启服务器后才恢复。

b3426f32fe558d94a645f387924af291.png

Tomcat下抛出Too many open files问题解析

分析

查看 ulimit -n 指令,发现文件句柄默认是1024,查看对应Tomcat进程(如下)

cat /proc/1787/limits #查看当前应用进程的句柄是4096lsof -p 1787 | wc -l #其中1787是对应的进程

发现已经超出4096了,导致后续已经无法操作文件句柄了,所以系统抛出异常,设备故障发生。

什么时候发生的

经过排查,发现是由一个操作引发的“时间同步”操作---因为系统是局域网内,设备终端的时间需要和系统保持一致,所以有时间同步操作这一功能,由于没有压测大量设备的情况,所以代码中也存在一定的隐患

private static final ThreadPoolExecutor deviceOpeartor=(ThreadPoolExecutor)Executors.new CachedThreadPool(); publicstaticFutureaddTask(PoolTypetype,Callabletask){  ThreadPoolExecutorpool=getPool(type);  returnpool.submit(task); } 

采用了默认的线程池newCachedThreadPool,池的大小是INT.MAX最大值(就是没限制了), 导致时间同步的任务加进去后,一下子全部执行了。

同时,Tomcat对webapp有一套自己的WebappClassLoader,它在启动的过程中会打开应用依赖的jar包来加载class信息, 但是过一段时间就会把打开的jar包全部关闭从而释放资源。然而如果后面需要加载某个新的class的时候,会把之前所有的jar包全部重新打开一遍, 然后再从中找到对应的jar来加载。加载完后过一段时间会再一次全部释放掉。

所以应用依赖的jar包越多,同时打开的文件句柄数也会越多。 2000台设备时间同步,一下子打开了过多的文件,导致文件句柄一下子超出了。故障就发生了

如何解决

1、代码优化

首先是代码层面的优化,采用阻塞队列

private static final ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("device-pool-%d").build();private static final ThreadPoolExecutor deviceThreadPool = new ThreadPoolExecutor(5, 100, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque(2048), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());

同时对于频繁的点击时间同步按钮,需要有机制通知之前队列中的任务还在执行,等待任务全部执行完毕后,再下一次操作

2、系统层面的调优

在不同批次的服务器上,有的服务器Max Open Files设置是65536;

但是一批新机器上的Max OpenFiles都被误设置为4096了。

这个需要运维帮忙重新修复一下,需要重启才会生效;具体的操作可以如下参考:

追加linux系统操作的句柄数 vim /etc/security/limits.conf追加* soft nofile 65536* hard nofile 65536

星号代表全局,soft为软件,hard为硬件,nofile为这里指可打开文件数。

配置修改完之后,需要重启后生效 以上操作是开发人员在排查的过程中可以自己来设置,具体系统层面的最好运维出面

#############################################################

要使limits.conf文件配置生效,必须要确保pam_limits.so文件被加入到启动文件中。 vim /etc/pam.d/login session required /lib/security/pam_limits.so

注意:这个一般最好不要编辑,会导致系统问题(可能无法启动,这个最好由运维来操作)

有时,发现上面设置了还是无效,还有一个办法,在Tomcat下bin中的startup.sh中来追加一行配置

ulimit -n 40960 #在os400=false这一行之前,加上文件句柄数,这个是针对当前Tomcat这个进程下的 os400=false

在实际使用过程中,会遇到各式各样的问题,尝试不同的方法去分析解决它

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值