2023拉

java.net.SocketException: Too many open files(转)

上一篇 / 下一篇  2012-07-05 14:52:04 / 个人分类:软件开发相关

      
部署到linux下的tomcat,今天发现包了“java.net.SocketException: Too many open files”,以前从来没有遇到过,在此记录一下:

彻底解决问题的是第三步, 所以,可以直接跳到第三步去看解决方法和步骤,当日第一、第二步是我不断探索,尝试解决问题的过程,虽然没有找到点上,但是还是有些意义的,因为linux切实有打开资源数量的限制,肯定需要修改的。

异常信息:

Java代码复制代码 收藏代码
  1. ............   
  2. Oct 172011 5:22:41 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run   
  3. SEVERE: Socket accept failed   
  4. java.net.SocketException: Too many open files   
  5.         at java.net.PlainSocketImpl.socketAccept(Native Method)   
  6.         at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375)   
  7.         at java.net.ServerSocket.implAccept(ServerSocket.java:470)   
  8.         at java.net.ServerSocket.accept(ServerSocket.java:438)   
  9.         at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:59)   
  10.         at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:210)   
  11.         at java.lang.Thread.run(Thread.java:636)   
  12. Oct 172011 5:22:43 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run   
  13. SEVERE: Socket accept failed   
  14. java.net.SocketException: Too many open files   
  15.         at java.net.PlainSocketImpl.socketAccept(Native Method)   
  16.         at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375)   
  17.         at java.net.ServerSocket.implAccept(ServerSocket.java:470)   
  18.         at java.net.ServerSocket.accept(ServerSocket.java:438)   
  19.         at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:59)   
  20.         at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:210)   
  21.         at java.lang.Thread.run(Thread.java:636)   
  22. Oct 172011 5:22:44 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run   
  23. SEVERE: Socket accept failed   
  24. java.net.SocketException: Too many open files   
  25.         at java.net.PlainSocketImpl.socketAccept(Native Method)   
  26.         at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375)   
  27.         at java.net.ServerSocket.implAccept(ServerSocket.java:470)   
  28.         at java.net.ServerSocket.accept(ServerSocket.java:438)   
  29.         at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:59)   
  30.         at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:210)   
  31.         at java.lang.Thread.run(Thread.java:636)   
  32. ............  
  1. ............  
  2. Oct 172011 5:22:41 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run  
  3. SEVERE: Socket accept failed  
  4. java.net.SocketException: Too many open files  
  5.         at java.net.PlainSocketImpl.socketAccept(Native Method)  
  6.         at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375)  
  7.         at java.net.ServerSocket.implAccept(ServerSocket.java:470)  
  8.         at java.net.ServerSocket.accept(ServerSocket.java:438)  
  9.         at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:59)  
  10.         at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:210)  
  11.         at java.lang.Thread.run(Thread.java:636)  
  12. Oct 172011 5:22:43 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run  
  13. SEVERE: Socket accept failed  
  14. java.net.SocketException: Too many open files  
  15.         at java.net.PlainSocketImpl.socketAccept(Native Method)  
  16.         at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375)  
  17.         at java.net.ServerSocket.implAccept(ServerSocket.java:470)  
  18.         at java.net.ServerSocket.accept(ServerSocket.java:438)  
  19.         at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:59)  
  20.         at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:210)  
  21.         at java.lang.Thread.run(Thread.java:636)  
  22. Oct 172011 5:22:44 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run  
  23. SEVERE: Socket accept failed  
  24. java.net.SocketException: Too many open files  
  25.         at java.net.PlainSocketImpl.socketAccept(Native Method)  
  26.         at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375)  
  27.         at java.net.ServerSocket.implAccept(ServerSocket.java:470)  
  28.         at java.net.ServerSocket.accept(ServerSocket.java:438)  
  29.         at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:59)  
  30.         at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:210)  
  31.         at java.lang.Thread.run(Thread.java:636)  
  32. ............  

原因:
   linux下有有文件限制,结果文件数操作最大限制,导致程序异常:问题是程序中有个静态方法打开文件时忘记关闭。两种解决方法,一是设置linux的最大文件打开数量(无法根本解决问题),二是解决程序中的bugs,即消除有问题的代码。

第一次解决
解决:
方法一、增大系统打开文件的数量(无法根本解决问题)、
   1、默认linux同时最大打开文件数量为1024个,用命令查看如下:ulimit -a:查看系统上受限资源的设置(open files (-n) 1024):

Java代码复制代码 收藏代码
  1. [root@**** bin]# ulimit -a   
  2. core file size          (blocks, -c) 0  
  3. data seg size           (kbytes, -d) unlimited   
  4. scheduling priority             (-e) 0  
  5. file size               (blocks, -f) unlimited   
  6. pending signals                 (-i) 16384  
  7. max locked memory       (kbytes, -l) 32  
  8. max memory size         (kbytes, -m) unlimited   
  9. open files                      (-n) 1024  
  10. pipe size            (512 bytes, -p) 8  
  11. POSIX message queues     (bytes, -q) 819200  
  12. real-time priority              (-r) 0  
  13. stack size              (kbytes, -s) 10240  
  14. cpu time               (seconds, -t) unlimited   
  15. max user processes              (-u) 16384  
  16. virtual memory          (kbytes, -v) unlimited   
  17. file locks                      (-x) unlimited   
  18. [root@**** bin]#  
  1. [root@**** bin]# ulimit -a  
  2. core file size          (blocks, -c) 0  
  3. data seg size           (kbytes, -d) unlimited  
  4. scheduling priority             (-e) 0  
  5. file size               (blocks, -f) unlimited  
  6. pending signals                 (-i) 16384  
  7. max locked memory       (kbytes, -l) 32  
  8. max memory size         (kbytes, -m) unlimited  
  9. open files                      (-n) 1024  
  10. pipe size            (512 bytes, -p) 8  
  11. POSIX message queues     (bytes, -q) 819200  
  12. real-time priority              (-r) 0  
  13. stack size              (kbytes, -s) 10240  
  14. cpu time               (seconds, -t) unlimited  
  15. max user processes              (-u) 16384  
  16. virtual memory          (kbytes, -v) unlimited  
  17. file locks                      (-x) unlimited  
  18. [root@**** bin]#  

2、可以修改同时打开文件的最大数基本可以解决:ulimit -n 4096

Java代码复制代码 收藏代码
  1. [root@**** bin]# ulimit -n 4096  
  2. [root@**** bin]# ulimit -a   
  3. core file size          (blocks, -c) 0  
  4. data seg size           (kbytes, -d) unlimited   
  5. scheduling priority             (-e) 0  
  6. file size               (blocks, -f) unlimited   
  7. pending signals                 (-i) 16384  
  8. max locked memory       (kbytes, -l) 32  
  9. max memory size         (kbytes, -m) unlimited   
  10. open files                      (-n) 4096  
  11. pipe size            (512 bytes, -p) 8  
  12. POSIX message queues     (bytes, -q) 819200  
  13. real-time priority              (-r) 0  
  14. stack size              (kbytes, -s) 10240  
  15. cpu time               (seconds, -t) unlimited   
  16. max user processes              (-u) 16384  
  17. virtual memory          (kbytes, -v) unlimited   
  18. file locks                      (-x) unlimited   
  19. [root@**** bin]#  
  1. [root@**** bin]# ulimit -n 4096  
  2. [root@**** bin]# ulimit -a  
  3. core file size          (blocks, -c) 0  
  4. data seg size           (kbytes, -d) unlimited  
  5. scheduling priority             (-e) 0  
  6. file size               (blocks, -f) unlimited  
  7. pending signals                 (-i) 16384  
  8. max locked memory       (kbytes, -l) 32  
  9. max memory size         (kbytes, -m) unlimited  
  10. open files                      (-n) 4096  
  11. pipe size            (512 bytes, -p) 8  
  12. POSIX message queues     (bytes, -q) 819200  
  13. real-time priority              (-r) 0  
  14. stack size              (kbytes, -s) 10240  
  15. cpu time               (seconds, -t) unlimited  
  16. max user processes              (-u) 16384  
  17. virtual memory          (kbytes, -v) unlimited  
  18. file locks                      (-x) unlimited  
  19. [root@**** bin]#  

已经修改了最大打开文件数。

方法二、修改程序中的bugs:
程序中有个静态的方法打开文件后,没有关闭文件,导致每次请求都会去打开文件,在程序中填入关闭输入流的操作即可以:
Java代码复制代码 收藏代码
  1. public static List<GpsPoint> getArrayList() throws IOException {   
  2.   
  3.         List<GpsPoint> pointList = null;   
  4.         // 读取配置文件  
  5.         InputStream in = ParseGpsFile.class.getClassLoader().getResourceAsStream("GPS1.TXT");   
  6.            
  7.         // 读路径出错,换另一种方式读取配置文件  
  8.         if (null == in) {   
  9.                
  10.             System.out.println("读取文件失败");   
  11.                
  12.             return pointList;   
  13.         }   
  14.            
  15.         pointList = new ArrayList<GpsPoint>();   
  16.            
  17.         try {   
  18.             BufferedReader br = new BufferedReader(new InputStreamReader(in));   
  19.             String longtude = "";   
  20.             String latude = "";   
  21.             String elevation = "";   
  22.             while ((longtude = br.readLine()) != null) {   
  23.                    
  24.                 // 读下一行数据,读纬度  
  25.                 latude = br.readLine();   
  26.                    
  27.                 if (null == latude) {   
  28.                        
  29.                     // 退出循环  
  30.                     break;   
  31.                 }   
  32.                    
  33.                 // 读下一行数据,读海拔  
  34.                 elevation = br.readLine();   
  35.                 if (null == latude) {   
  36.                        
  37.                     // 退出循环  
  38.                     break;   
  39.                 }   
  40.                    
  41.                 // 加入一个点  
  42.                 pointList.add(gps2point(longtude, latude, elevation));   
  43.             }   
  44.                
  45.             in.close();   
  46.             System.out.println("\n\n");   
  47.         } catch (Exception e) {   
  48.                
  49.             in.close();   
  50.             e.printStackTrace();   
  51.         }   
  52.            
  53.         return pointList;   
  54.     }  
  1. public static List<GpsPoint> getArrayList() throws IOException {  
  2.   
  3.         List<GpsPoint> pointList = null;  
  4.         // 读取配置文件  
  5.         InputStream in = ParseGpsFile.class.getClassLoader().getResourceAsStream("GPS1.TXT");  
  6.           
  7.         // 读路径出错,换另一种方式读取配置文件  
  8.         if (null == in) {  
  9.               
  10.             System.out.println("读取文件失败");  
  11.               
  12.             return pointList;  
  13.         }  
  14.           
  15.         pointList = new ArrayList<GpsPoint>();  
  16.           
  17.         try {  
  18.             BufferedReader br = new BufferedReader(new InputStreamReader(in));  
  19.             String longtude = "";  
  20.             String latude = "";  
  21.             String elevation = "";  
  22.             while ((longtude = br.readLine()) != null) {  
  23.                   
  24.                 // 读下一行数据,读纬度  
  25.                 latude = br.readLine();  
  26.                   
  27.                 if (null == latude) {  
  28.                       
  29.                     // 退出循环  
  30.                     break;  
  31.                 }  
  32.                   
  33.                 // 读下一行数据,读海拔  
  34.                 elevation = br.readLine();  
  35.                 if (null == latude) {  
  36.                       
  37.                     // 退出循环  
  38.                     break;  
  39.                 }  
  40.                   
  41.                 // 加入一个点  
  42.                 pointList.add(gps2point(longtude, latude, elevation));  
  43.             }  
  44.               
  45.             in.close();  
  46.             System.out.println("\n\n");  
  47.         } catch (Exception e) {  
  48.               
  49.             in.close();  
  50.             e.printStackTrace();  
  51.         }  
  52.           
  53.         return pointList;  
  54.     }  


问题彻底解决

-----
第二次解决:
实际测试后发现这个问题还没有解决,最终又找了些方法,经过一段时间的测试,似乎解决了问题:

具体步骤如下:
linux为redhat服务器版本(非个人版),必须设置的内容:

1、/etc/pam.d/login 添加
Java代码复制代码 收藏代码
  1. session required     /lib/security/pam_limits.so  
  1. session required     /lib/security/pam_limits.so  

# 注意看这个文件的注释
具体文件的内容为:
Java代码复制代码 收藏代码
  1. [root@**** ~]# vi /etc/pam.d/login   
  2. #%PAM-1.0  
  3. auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so   
  4. auth       include      system-auth   
  5. account    required     pam_nologin.so   
  6. account    include      system-auth   
  7. password   include      system-auth   
  8. # pam_selinux.so close should be the first session rule   
  9. session    required     pam_selinux.so close   
  10. session    optional     pam_keyinit.so force revoke   
  11. session    required     pam_loginuid.so   
  12. session    include      system-auth   
  13. session    optional     pam_console.so   
  14. # pam_selinux.so open should only be followed by sessions to be executed in the user context   
  15. session    required     pam_selinux.so open   
  16.   
  17. ~   
  18. "/etc/pam.d/login" 15L, 644C  
  1. [root@**** ~]# vi /etc/pam.d/login  
  2. #%PAM-1.0  
  3. auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so  
  4. auth       include      system-auth  
  5. account    required     pam_nologin.so  
  6. account    include      system-auth  
  7. password   include      system-auth  
  8. # pam_selinux.so close should be the first session rule  
  9. session    required     pam_selinux.so close  
  10. session    optional     pam_keyinit.so force revoke  
  11. session    required     pam_loginuid.so  
  12. session    include      system-auth  
  13. session    optional     pam_console.so  
  14. # pam_selinux.so open should only be followed by sessions to be executed in the user context  
  15. session    required     pam_selinux.so open  
  16.   
  17. ~  
  18. "/etc/pam.d/login" 15L, 644C  

修改后的内容:

Java代码复制代码 收藏代码
  1. -bash: [root@****: command not found   
  2. [root@**** ~]# clear   
  3. [root@**** ~]# cat /etc/pam.d/login   
  4. #%PAM-1.0  
  5. auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so   
  6. auth       include      system-auth   
  7. account    required     pam_nologin.so   
  8. account    include      system-auth   
  9. password   include      system-auth   
  10. # pam_selinux.so close should be the first session rule   
  11. session    required     pam_selinux.so close   
  12. session    optional     pam_keyinit.so force revoke   
  13. session    required     pam_loginuid.so   
  14. session    include      system-auth   
  15. session    optional     pam_console.so   
  16. # pam_selinux.so open should only be followed by sessions to be executed in the user context   
  17. session    required     pam_selinux.so open   
  18. # kevin.xie added, fixed 'too many open file' bug, limit open max files 10242011

TAG:

 

评分:0

我来说两句

Open Toolbar