centos7 tomcat_CentOS7下Tomcat应用容器抛出Too many open files问题
背景
在實(shí)際開發(fā)中有一款設(shè)備管理軟件,一般情況下接入的設(shè)備并不多,最多幾十臺(tái);最近有一個(gè)項(xiàng)目中,需要接入2000臺(tái)這樣的設(shè)備,運(yùn)行一段時(shí)間后,會(huì)大量拋出Too many open files;導(dǎo)致設(shè)備無法正常使用,重啟服務(wù)器后才恢復(fù)。
Tomcat下拋出Too many open files問題解析
分析
查看 ulimit -n 指令,發(fā)現(xiàn)文件句柄默認(rèn)是1024,查看對(duì)應(yīng)Tomcat進(jìn)程(如下)
cat /proc/1787/limits #查看當(dāng)前應(yīng)用進(jìn)程的句柄是4096lsof -p 1787 | wc -l #其中1787是對(duì)應(yīng)的進(jìn)程發(fā)現(xiàn)已經(jīng)超出4096了,導(dǎo)致后續(xù)已經(jīng)無法操作文件句柄了,所以系統(tǒng)拋出異常,設(shè)備故障發(fā)生。
什么時(shí)候發(fā)生的
經(jīng)過排查,發(fā)現(xiàn)是由一個(gè)操作引發(fā)的“時(shí)間同步”操作---因?yàn)橄到y(tǒng)是局域網(wǎng)內(nèi),設(shè)備終端的時(shí)間需要和系統(tǒng)保持一致,所以有時(shí)間同步操作這一功能,由于沒有壓測(cè)大量設(shè)備的情況,所以代碼中也存在一定的隱患
private static final ThreadPoolExecutor deviceOpeartor=(ThreadPoolExecutor)Executors.new CachedThreadPool(); publicstaticFutureaddTask(PoolTypetype,Callabletask){ ThreadPoolExecutorpool=getPool(type); returnpool.submit(task); }采用了默認(rèn)的線程池newCachedThreadPool,池的大小是INT.MAX最大值(就是沒限制了), 導(dǎo)致時(shí)間同步的任務(wù)加進(jìn)去后,一下子全部執(zhí)行了。
同時(shí),Tomcat對(duì)webapp有一套自己的WebappClassLoader,它在啟動(dòng)的過程中會(huì)打開應(yīng)用依賴的jar包來加載class信息, 但是過一段時(shí)間就會(huì)把打開的jar包全部關(guān)閉從而釋放資源。然而如果后面需要加載某個(gè)新的class的時(shí)候,會(huì)把之前所有的jar包全部重新打開一遍, 然后再?gòu)闹姓业綄?duì)應(yīng)的jar來加載。加載完后過一段時(shí)間會(huì)再一次全部釋放掉。
所以應(yīng)用依賴的jar包越多,同時(shí)打開的文件句柄數(shù)也會(huì)越多。 2000臺(tái)設(shè)備時(shí)間同步,一下子打開了過多的文件,導(dǎo)致文件句柄一下子超出了。故障就發(fā)生了
如何解決
1、代碼優(yōu)化
首先是代碼層面的優(yōu)化,采用阻塞隊(duì)列
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());同時(shí)對(duì)于頻繁的點(diǎn)擊時(shí)間同步按鈕,需要有機(jī)制通知之前隊(duì)列中的任務(wù)還在執(zhí)行,等待任務(wù)全部執(zhí)行完畢后,再下一次操作
2、系統(tǒng)層面的調(diào)優(yōu)
在不同批次的服務(wù)器上,有的服務(wù)器Max Open Files設(shè)置是65536;
但是一批新機(jī)器上的Max OpenFiles都被誤設(shè)置為4096了。
這個(gè)需要運(yùn)維幫忙重新修復(fù)一下,需要重啟才會(huì)生效;具體的操作可以如下參考:
追加linux系統(tǒng)操作的句柄數(shù) vim /etc/security/limits.conf追加* soft nofile 65536* hard nofile 65536星號(hào)代表全局,soft為軟件,hard為硬件,nofile為這里指可打開文件數(shù)。
配置修改完之后,需要重啟后生效 以上操作是開發(fā)人員在排查的過程中可以自己來設(shè)置,具體系統(tǒng)層面的最好運(yùn)維出面
#############################################################
要使limits.conf文件配置生效,必須要確保pam_limits.so文件被加入到啟動(dòng)文件中。 vim /etc/pam.d/login session required /lib/security/pam_limits.so注意:這個(gè)一般最好不要編輯,會(huì)導(dǎo)致系統(tǒng)問題(可能無法啟動(dòng),這個(gè)最好由運(yùn)維來操作)
有時(shí),發(fā)現(xiàn)上面設(shè)置了還是無效,還有一個(gè)辦法,在Tomcat下bin中的startup.sh中來追加一行配置
ulimit -n 40960 #在os400=false這一行之前,加上文件句柄數(shù),這個(gè)是針對(duì)當(dāng)前Tomcat這個(gè)進(jìn)程下的 os400=false在實(shí)際使用過程中,會(huì)遇到各式各樣的問題,嘗試不同的方法去分析解決它
總結(jié)
以上是生活随笔為你收集整理的centos7 tomcat_CentOS7下Tomcat应用容器抛出Too many open files问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么疫情会导致房价下跌呢?
- 下一篇: 有比较好的家用电热水器推荐吗?