• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

记一次Java程序导致的linux句柄泄露too many open files

武飞扬头像
哇卡哇卡aaa
帮助1

目录

一、问题描述

二、排查问题原因

三、句柄泄露问题解决方案总结:


一、问题描述

生产服项目运行了很久了,突然有一天访问失败,查看日志发现报错信息如下

  1.  
    14-Oct-2022 10:09:34.728 WARNING [Catalina-utility-1] org.apache.catalina.users.MemoryUserDatabase.backgroundProcess Failed to close [conf/tomcat-users.xml]
  2.  
    java.io.FileNotFoundException: /home/btfb/btfbServer/conf/tomcat-users.xml (Too many open files)
  3.  
    at java.io.FileInputStream.open(Native Method)
  4.  
    at java.io.FileInputStream.<init>(FileInputStream.java:131)
  5.  
    at java.io.FileInputStream.<init>(FileInputStream.java:87)
  6.  
    at sun.net.www.protocol.file.FileURLConnection.connect(FileURLConnection.java:90)
  7.  
    at sun.net.www.protocol.file.FileURLConnection.getInputStream(FileURLConnection.java:188)
  8.  
    at org.apache.catalina.users.MemoryUserDatabase.backgroundProcess(MemoryUserDatabase.java:685)
  9.  
    at org.apache.catalina.realm.UserDatabaseRealm.backgroundProcess(UserDatabaseRealm.java:143)
  10.  
    at org.apache.catalina.realm.CombinedRealm.backgroundProcess(CombinedRealm.java:301)
  11.  
    at org.apache.catalina.core.ContainerBase.backgroundProcess(ContainerBase.java:1137)
  12.  
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.processChildren(ContainerBase.java:1353)
  13.  
    at org.apache.catalina.core.ContainerBase$ContainerBackgroundProcessor.run(ContainerBase.java:1335)
  14.  
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
  15.  
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
  16.  
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
  17.  
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
  18.  
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  19.  
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  20.  
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  21.  
    at java.lang.Thread.run(Thread.java:745)
学新通

 从字面意思看就是文件打开太多了,此时怀疑是句柄超多最大值了

二、排查问题原因

查看linux最大句柄数:ulimit -a,其中open files就是linux设置的最大句柄数(默认1024)

学新通

也可以直接使用ulimit -n

学新通

 查询句柄数是被哪个进程占了(第一列是句柄数,第二列是进程号):

lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|more

学新通

 查看占用句柄量高的是什么应用:ps -ef|grep 22186(22186为进程号)

学新通

 如上图可以看出是Tomcat占用了大量句柄,并且此Tomcat为生产Tomcat,不能直接关闭,因此排查项目代码中是否有未关闭的IO流或者未关闭的连接等,通过排查发现最近写了一个使用snmp推送消息的接口,并且此接口是做的定时任务,每半个小时调用一次,由于是第一次接触snmp,所有忘了关闭连接,结果导致句柄泄露

 学新通

三、句柄泄露问题解决方案总结:

其实Linux是有文件句柄限制的,而且默认不是很高,一般都是1024,作为一台生产服务器,其实很容易就达到 这个数量,因此我们需要把这个值改大一些。我们可以用ulimit -n 来查看当前用户句柄数限制。那么这个1024是系统的限制,还是用户的限制呢。其实,这个是用户限制来的,完整的说法,应该是当前用户准备要运行的程序的限制。

情况一:服务器句柄数确实不够用,增大文件句柄数

        增大文件句柄数。这种方式能及时解决问题,但是不能够彻底的解决问题,可以为彻底解决问题提供一定的时间保证。那么如何增大文件句柄数数呢?

如修改文件句柄数为65535,ulimit -n 65535.此时系统的文件句柄数为65535.

2)将ulimit 值添加到/etc/profile文件中(适用于有root权限登录的系统)

为了每次系统重新启动时,都可以获取更大的ulimit值,将ulimit 加入到/etc/profile 文件底部。

echo ulimit -n 65535 >>/etc/profile

source /etc/profile #加载修改后的profile

ulimit -n #显示65535,修改完毕!

到此为止,你以为大功告成了么,其实不然,突然发现自己再次登录进来的时候,ulimit的值还是1024,这是为什么呢? 用户登录的时候执行sh脚本的顺序:

/etc/profile.d/file

/etc/profile

/etc/bashrc

/mingjie/.bashrc

/mingjie/.bash_profile

由于ulimit -n的脚本命令加载在第二部分,用户登录时由于权限原因在第二步还不能完成ulimit的修改,所以ulimit的值还是系统默认的1024。所以想彻底改变这种问题,就必须做如下操作:修改/etc/security/limits.conf

里面有很详细的注释,比如

* soft nofile 2048

* hard nofile 32768

就可以将文件句柄限制统一改成软2048,硬32768

那么什么是软限制,什么是硬限制 ?

硬限制是实际的限制,而软限制,是warnning限制,只会做出warning

这样就实际地增大了文件句柄数。

情况二:代码中有未关闭的连接或io流等,找到该处代码,该关闭的都及时关闭

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhghahfb
系列文章
更多 icon
同类精品
更多 icon
继续加载