java.net.SocketException: Too many open files问题分析及解决方案

    xiaoxiao2021-03-28  25

    Java web应用在执行一段时间之后出现了这么个问题

    [java]  view plain  copy java.net.SocketException: Too many open files           at java.net.PlainSocketImpl.socketAccept(Native Method)           at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)           at java.net.ServerSocket.implAccept(ServerSocket.java:453)           at java.net.ServerSocket.accept(ServerSocket.java:421)           at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:60)           at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:216)  

     用ulimit -a看看Linux打开文件限制

    [java]  view plain  copy [admin@test ~]# ulimit -a   core file size          (blocks, -c) 0   data seg size           (kbytes, -d) unlimited   scheduling priority             (-e) 0   file size               (blocks, -f) unlimited   pending signals                 (-i) 360448   max locked memory       (kbytes, -l) 32   max memory size         (kbytes, -m) unlimited   open files                      (-n) 1024   pipe size            (512 bytes, -p) 8   POSIX message queues     (bytes, -q) 819200   real-time priority              (-r) 0   stack size              (kbytes, -s) 10240   cpu time               (seconds, -t) unlimited   max user processes              (-u) 360448   virtual memory          (kbytes, -v) unlimited   file locks                      (-x) unlimited  

     

    [java]  view plain  copy 用lsof -p [进程ID] 可以看到某ID的打开文件状况。进程ID可能用 ps -ef|grep java列出  

     

    [java]  view plain  copy [admin@test ~]# lsof -p 1940   COMMAND  PID USER   FD   TYPE             DEVICE     SIZE      NODE NAME   java    1940 admin  cwd    DIR               0,68     4096 385090717 /admin/apache-tomcat-7.0.39/bin   java    1940 admin  rtd    DIR               0,68     4096 384141801 /   java    1940 admin  txt    REG               0,68    47308 385122308 /admin/jdk1.6.0_13/jre/bin/java   java    1940 admin  mem    REG              202,3          385122339 /admin/jdk1.6.0_13/jre/lib/i386/client/libjvm.so (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122308 /admin/jdk1.6.0_13/jre/bin/java (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122425 /admin/jdk1.6.0_13/jre/lib/i386/client/classes.jsa (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122426 /admin/jdk1.6.0_13/jre/lib/charsets.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          384959153 /lib/libresolv-2.12.so (path dev=0,68)   java    1940 admin  mem    REG              202,3          384959143 /lib/libnss_dns-2.12.so (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122355 /admin/jdk1.6.0_13/jre/lib/i386/libnio.so (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122354 /admin/jdk1.6.0_13/jre/lib/i386/libnet.so (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122325 /admin/jdk1.6.0_13/jre/lib/ext/sunjce_provider.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122326 /admin/jdk1.6.0_13/jre/lib/ext/sunpkcs11.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122392 /admin/jdk1.6.0_13/jre/lib/jce.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122405 /admin/jdk1.6.0_13/jre/lib/resources.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385122391 /admin/jdk1.6.0_13/jre/lib/jsse.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385090820 /admin/apache-tomcat-7.0.39/lib/tomcat-dbcp.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385090824 /admin/apache-tomcat-7.0.39/lib/tomcat-jdbc.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385090821 /admin/apache-tomcat-7.0.39/lib/tomcat-i18n-es.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385090816 /admin/apache-tomcat-7.0.39/lib/jsp-api.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385090817 /admin/apache-tomcat-7.0.39/lib/servlet-api.jar (path dev=0,68)   java    1940 admin  mem    REG              202,3          385090813 /admin/apache-tomcat-7.0.39/lib/el-api.jar (path dev=0,68)  

     

    通过以上命令,我们可以看到open files 的最大数为1024 那么我们可以通过一下命令修改该参数的最大值 2. ulimit -n 4096 [root@test security]# ulimit -n 4096 [root@test security]# ulimit -a core file size        (blocks, -c) 0 data seg size         (kbytes, -d) unlimited file size             (blocks, -f) unlimited max locked memory     (kbytes, -l) unlimited max memory size       (kbytes, -m) unlimited open files                    (-n) 4096 pipe size          (512 bytes, -p) 8 stack size            (kbytes, -s) 8192 cpu time             (seconds, -t) unlimited max user processes            (-u) 7168 virtual memory        (kbytes, -v) unlimited

    这样我们就修改了系统在同一时间打开文件资源的最大数,基本解决以上问题。

    以上部分是查找网络上的解决方法。设置了之后段时间内有作用。

    后来仔细想来,问题还是要从根本上解决,于是把以前的代码由认真地看了一遍。终于找到了,罪魁祸首。

    在读取文件时,有一些使用的BufferedReader 没有关闭。导致文件一直处于打开状态。造成资源的严重浪费。

    修改之后的简单代码如下:

    public     void   test(){     BufferedReader reader   null  ;       try  {         reader    读取文件;         String line      ""  ;           while  ( ( ine  reader.readLine())  !=  null  ){            其他操作         }     }   catch   (IOException e){         System.out.println(e);     }   finally  {              if  (reader   !=  null  ){                   try   {                     reader.close();                 }   catch   (IOException e) {                       e.printStackTrace();                 }           }     } }

     **********************************************************************************************************************************************

    因为Socket没有释放,以致文件句柄用完了.如果用HttpClient去调用的, HttpClient本身存在这个问题, 解决方式就是加个httpHeader, 使用HttpClient如下: Java代码  client = new HttpClient();   client.getParams().setBooleanParameter("http.protocol.expect-continue"false);   HttpMethod httpMethod = ...;   httpMethod.addRequestHeader("Connection""close");   client.executeMethod(httpMethod);   [java]  view plain  copy client = new HttpClient();           client.getParams().setBooleanParameter("http.protocol.expect-continue"false);   HttpMethod httpMethod = ...;   httpMethod.addRequestHeader("Connection""close");   client.executeMethod(httpMethod);   , 其它的API应该也可以加这两个值. 用unlimit放大操作系统最大打开文件数的确可以短时间解决 Too many open files的现象,但这不是本质原因。  本质原因肯定能够是你的程序中没有及时close掉文件(在linux/unix中Socket也是文件)。否则只有在上千的绝对同时并发时,才可能出现Too many open files错误。
    转载请注明原文地址: https://ju.6miu.com/read-664725.html

    最新回复(0)