異常信息: java
............ Oct 17, 2011 5:22:41 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run SEVERE: Socket accept failed java.net.SocketException: Too many open files at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375) at java.net.ServerSocket.implAccept(ServerSocket.java:470) at java.net.ServerSocket.accept(ServerSocket.java:438) at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:59) at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:210) at java.lang.Thread.run(Thread.java:636) Oct 17, 2011 5:22:43 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run SEVERE: Socket accept failed java.net.SocketException: Too many open files at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375) at java.net.ServerSocket.implAccept(ServerSocket.java:470) at java.net.ServerSocket.accept(ServerSocket.java:438) at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:59) at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:210) at java.lang.Thread.run(Thread.java:636) Oct 17, 2011 5:22:44 PM org.apache.tomcat.util.net.JIoEndpoint$Acceptor run SEVERE: Socket accept failed java.net.SocketException: Too many open files at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375) at java.net.ServerSocket.implAccept(ServerSocket.java:470) at java.net.ServerSocket.accept(ServerSocket.java:438) at org.apache.tomcat.util.net.DefaultServerSocketFactory.acceptSocket(DefaultServerSocketFactory.java:59) at org.apache.tomcat.util.net.JIoEndpoint$Acceptor.run(JIoEndpoint.java:210) at java.lang.Thread.run(Thread.java:636) ............
緣由:
一、默認linux同時最大打開文件數量爲1024個,用命令查看以下:ulimit -a:查看系統上受限資源的設置(open files (-n) 1024): mysql
[root@**** bin]# 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) 16384 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) 16384 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited [root@**** bin]#
二、能夠修改同時打開文件的最大數基本能夠解決:ulimit -n 4096 linux
[root@**** bin]# ulimit -n 4096 [root@**** bin]# 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) 16384 max locked memory (kbytes, -l) 32 max memory size (kbytes, -m) unlimited open files (-n) 4096 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) 16384 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited [root@**** bin]#
已經修改了最大打開文件數。
程序中有個靜態的方法打開文件後,沒有關閉文件,致使每次請求都會去打開文件,在程序中填入關閉輸入流的操做便可以: sql
public static List<GpsPoint> getArrayList() throws IOException { List<GpsPoint> pointList = null; // 讀取配置文件 InputStream in = ParseGpsFile.class.getClassLoader().getResourceAsStream("GPS1.TXT"); // 讀路徑出錯,換另外一種方式讀取配置文件 if (null == in) { System.out.println("讀取文件失敗"); return pointList; } pointList = new ArrayList<GpsPoint>(); try { BufferedReader br = new BufferedReader(new InputStreamReader(in)); String longtude = ""; String latude = ""; String elevation = ""; while ((longtude = br.readLine()) != null) { // 讀下一行數據,讀緯度 latude = br.readLine(); if (null == latude) { // 退出循環 break; } // 讀下一行數據,讀海拔 elevation = br.readLine(); if (null == latude) { // 退出循環 break; } // 加入一個點 pointList.add(gps2point(longtude, latude, elevation)); } in.close(); System.out.println("\n\n"); } catch (Exception e) { in.close(); e.printStackTrace(); } return pointList; }
問題完全解決
一、/etc/pam.d/login 添加 shell
session required /lib/security/pam_limits.so
# 注意看這個文件的註釋
具體文件的內容爲: apache
[root@**** ~]# vi /etc/pam.d/login #%PAM-1.0 auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so auth include system-auth account required pam_nologin.so account include system-auth password include system-auth # pam_selinux.so close should be the first session rule session required pam_selinux.so close session optional pam_keyinit.so force revoke session required pam_loginuid.so session include system-auth session optional pam_console.so # pam_selinux.so open should only be followed by sessions to be executed in the user context session required pam_selinux.so open ~ "/etc/pam.d/login" 15L, 644C
修改後的內容:tomcat
-bash: [root@**** : command not found [root@**** ~]# clear [root@**** ~]# cat /etc/pam.d/login #%PAM-1.0 auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so auth include system-auth account required pam_nologin.so account include system-auth password include system-auth # pam_selinux.so close should be the first session rule session required pam_selinux.so close session optional pam_keyinit.so force revoke session required pam_loginuid.so session include system-auth session optional pam_console.so # pam_selinux.so open should only be followed by sessions to be executed in the user context session required pam_selinux.so open # kevin.xie added, fixed 'too many open file' bug, limit open max files 1024, 2011-10-24 session required /lib/security/pam_limits.so [root@**** ~]#
2. /etc/security/limits.conf 添加 bash
root – nofile 1006154
root 是一個用戶,若是是想全部用戶生效的話換成 * ,設置的數值與硬件配置有關,別設置太大了。
修改前內容 服務器
[root@**** ~]# cat /etc/security/limits.conf # /etc/security/limits.conf # #Each line describes a limit for a user in the form: # #<domain> <type> <item> <value> # #Where: #<domain> can be: # - an user name # - a group name, with @group syntax # - the wildcard *, for default entry # - the wildcard %, can be also used with %group syntax, # for maxlogin limit # #<type> can have the two values: # - "soft" for enforcing the soft limits # - "hard" for enforcing hard limits # #<item> can be one of the following: # - core - limits the core file size (KB) # - data - max data size (KB) # - fsize - maximum filesize (KB) # - memlock - max locked-in-memory address space (KB) # - nofile - max number of open files # - rss - max resident set size (KB) # - stack - max stack size (KB) # - cpu - max CPU time (MIN) # - nproc - max number of processes # - as - address space limit # - maxlogins - max number of logins for this user # - maxsyslogins - max number of logins on the system # - priority - the priority to run user process with # - locks - max number of file locks the user can hold # - sigpending - max number of pending signals # - msgqueue - max memory used by POSIX message queues (bytes) # - nice - max nice priority allowed to raise to # - rtprio - max realtime priority # #<domain> <type> <item> <value> # #* soft core 0 #* hard rss 10000 #@student hard nproc 20 #@faculty soft nproc 20 #@faculty hard nproc 50 #ftp hard nproc 0 #@student - maxlogins 4 # End of file [root@**** ~]# [root@**** ~]# cat /etc/security/limits.conf # /etc/security/limits.conf # #Each line describes a limit for a user in the form: # #<domain> <type> <item> <value> # #Where: #<domain> can be: # - an user name # - a group name, with @group syntax # - the wildcard *, for default entry # - the wildcard %, can be also used with %group syntax, # for maxlogin limit # #<type> can have the two values: # - "soft" for enforcing the soft limits # - "hard" for enforcing hard limits # #<item> can be one of the following: # - core - limits the core file size (KB) # - data - max data size (KB) # - fsize - maximum filesize (KB) # - memlock - max locked-in-memory address space (KB) # - nofile - max number of open files # - rss - max resident set size (KB) # - stack - max stack size (KB) # - cpu - max CPU time (MIN) # - nproc - max number of processes # - as - address space limit # - maxlogins - max number of logins for this user # - maxsyslogins - max number of logins on the system # - priority - the priority to run user process with # - locks - max number of file locks the user can hold # - sigpending - max number of pending signals # - msgqueue - max memory used by POSIX message queues (bytes) # - nice - max nice priority allowed to raise to # - rtprio - max realtime priority # #<domain> <type> <item> <value> # #* soft core 0 #* hard rss 10000 #@student hard nproc 20 #@faculty soft nproc 20 #@faculty hard nproc 50 #ftp hard nproc 0 #@student - maxlogins 4 # kevin.xie added, fixed 'too many open file' bug, limit open max files 1024, 2011-10-24 * - nofile 102400 # End of file [root@**** ~]#
修改後的內容 網絡
3. 修改 /etc/rc.local 添加
echo 8061540 > /proc/sys/fs/file-max
修改前內容
[root@**** ~]# cat /proc/sys/fs/file-max 4096 [root@**** ~]#
修改後內容
[root@**** ~]# cat /proc/sys/fs/file-max 4096000 [root@**** ~]#
作完3個步驟,就能夠了。
原來的程序:
/** * <pre><b>功能描述:</b>獲取異步的session實例。 * * @author :Kevin.xie * <b>建立日期 :</b>2011-9-15 上午10:06:27 * * @return * * <b>修改歷史:</b>(修改人,修改時間,修改緣由/內容) * * </pre> */ public static IoSession getSession1() { // 建立客戶端鏈接器 IoConnector connector = new NioSocketConnector(); // 設置事件處理器 connector.setHandler(new WebClientHandler()); // 設置編碼過濾器和按行讀取數據模式 connector.getFilterChain() .addLast("codec", new ProtocolCodecFilter(new ObdDemuxingProtocolCodecFactory(false))); // 建立鏈接 ConnectFuture future = connector.connect(new InetSocketAddress(ServerConfigBoundle.getServerIp(), ServerConfigBoundle.getServerPort())); // 等待鏈接建立完成 future.awaitUninterruptibly(); // 獲取鏈接會話 IoSession session = future.getSession(); return session; } /** * <pre><b>功能描述:</b>必需要關閉Connector和IoSession * @author :Kevin.xie * <b>建立日期 :</b>2011-10-20 上午10:20:54 * * @param session 要關閉的session * * <b>修改歷史:</b>(修改人,修改時間,修改緣由/內容) * * </pre> */ public static void closeSession(IoSession session) { if (session != null && !session.isClosing()) { // 沒有關閉,就關閉 session.close(true); session = null; } }
修改後的程序
/** * * <pre><b>功能描述:</b>獲取IoConnector和異步的session實例 * 沒法關閉。特別的提醒,NioSocketConnector 也要關閉。 * 函數名是 dispose()。這點特別重要。此次出現 too many open files 的問題根源在這裏 * * @author :Kevin.xie * <b>建立日期 :</b>2011-9-15 上午10:06:27 * * @return * * <b>修改歷史:</b>(修改人,修改時間,修改緣由/內容) * * </pre> */ public static Map<String, Object> getConnectorAndSession() { // 建立客戶端鏈接器 IoConnector connector = new NioSocketConnector(); // 設置事件處理器 connector.setHandler(new WebClientHandler()); // 設置編碼過濾器和按行讀取數據模式 connector.getFilterChain() .addLast("codec", new ProtocolCodecFilter(new ObdDemuxingProtocolCodecFactory(false))); // 建立鏈接 ConnectFuture future = connector.connect(new InetSocketAddress(ServerConfigBoundle.getServerIp(), ServerConfigBoundle.getServerPort())); // 等待鏈接建立完成 future.awaitUninterruptibly(); // 獲取鏈接會話 IoSession session = future.getSession(); Map<String, Object> map = new HashMap<String, Object>(); map.put(CONNECTOR_KEY, connector); map.put(SESSION_KEY, session); return map; } /** * * <pre><b>功能描述:</b>必需要關閉Connector和IoSession * 特別的提醒,NioSocketConnector 也要關閉。 * 函數名是 dispose()。這點特別重要。此次出現 too many open files 的問題根源在這裏 * @author :Kevin.xie * <b>建立日期 :</b>2011-10-20 上午10:20:54 * * @param connector 要關閉的IoConnector,不關閉會報 too many open files 錯誤 * @param session 要關閉的session * * <b>修改歷史:</b>(修改人,修改時間,修改緣由/內容) * * </pre> */ public static void closeConnectorAndSession(IoConnector connector, IoSession session) { if (session != null && !session.isClosing()) { // 沒有關閉,就關閉 session.close(true); session = null; } if (connector != null && !(connector.isDisposing() || connector.isDisposed())) { // 沒有關閉,就關閉 connector.dispose(); connector = null; } } ]
用完後必定要釋放資源:
Map<String, Object> resultMap = SocketUtils.getConnectorAndSession(); IoSession session = (IoSession) resultMap.get(SocketUtils.SESSION_KEY); IoConnector connector = (IoConnector) resultMap.get(SocketUtils.CONNECTOR_KEY); ............ ............ // 主動關閉鏈接 SocketUtils.closeConnectorAndSession(connector, session);
同時在配置文件 /etc/security/limits.conf 加了一個配置(該不應問題不大):
* hard nofile 65536
# 第二次解決添加的內容 # kevin.xie added, fixed 'too many open file' bug, limit open max files 1024, 2011-10-24 * - nofile 102400 # 第三次(本次)解決添加的問題(不過這個應該能夠不修改,沒有印證,也懶得修改了) # kevin.xie added, fixed 'too many open file' bug', 2012-01-04 * soft nofile 65536 * hard nofile 65536