1. 程式人生 > >Linux下tomcat報錯“java.net.SocketException: Too many open files”--MINA2 錯誤解決

Linux下tomcat報錯“java.net.SocketException: Too many open files”--MINA2 錯誤解決

轉載:

因為這個問題,我也是經過三次修改後,才徹底解決該問題。我是遇到了錯誤資訊:“Too many open files”和“No buffer space availabel”,從我的專案上看,兩個問題都是因為使用MINA2時,有些資源沒有關閉造成的。但是出現“Too many open files”的錯誤(linux上面,windows下沒有發現該問題) ,肯定是因為linux下對每個程序開啟系統資源數的限制,預設是1024,打開了資源沒有釋放。所以如果是“Too many open files”錯誤,肯定是你的程式裡打開了資源沒有釋放!

    剛開始遇到這個錯誤,我也以為是linux自己配置的的問題,節後解決過程如下:
第一次解決,因為對linux不是很熟悉,以為是linux伺服器配置的問題(預設安裝的配置) :
       按上面的步驟(第一和第二步修改,方法一和方法2都修改了),情況好轉,以為解決了。但時間一長問題又重現了。因為開始系統開啟的資源少,所以問題重現的時間間隔就比較長。人因都是人為傳送請求。所以有時時候一兩個星期都不出現,如果操作平率高的話,就出現快點了。

第二次解決,因為發現第一次方法沒有解決好問題。依然以為是linux配置的問題,在第一次的基礎上,所以又看了資料,於是有了第二次解決,方法就是按上面的第三步的操作,修改了一些配置檔案。該完後,發現情況好了很多,兩三個星期都不見有問題。但後來程式上使用的定時排程任務,每隔幾分鐘會就會開啟十幾個請求連結,這樣一跑,快的話,不到半個小時就出現問題了。

第三次解決,這次基本上不認為是伺服器本省的問題,肯定是程式那裡出問題,所以又看了很多資料,最後終於解決了問題(經過測試,目前其了5個任務,每個人物6個執行緒,所有任務基本在20~5分鐘內完成,比第二修改後的任務多了5倍這樣,請求時間間隔也短了很多),經過7天的執行,沒有再出現過一次這樣的錯誤。

問題的原因是:原來的MINA2程式之關了IoSession,並沒有關閉IoConnector例項,但恰恰就是因為沒有關閉每次開啟的IoConnector例項,造成了"Too many open files ".

具體看原帖,我已在後面更新了

部署到linux下的tomcat,今天發現包了“java.net.SocketException: Too many open files”,以前從來沒有遇到過,在此記錄一下: 

徹底解決問題的是第三步, 所以,可以直接跳到第三步去看解決方法和步驟,當日第一、第二步是我不斷探索,嘗試解決問題的過程,雖然沒有找到點上,但是還是有些意義的,因為linux切實有開啟資源數量的限制,肯定需要修改的。 

異常資訊: 
 

Java程式碼 

  1. ......
    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下有有檔案限制,結果檔案數操作最大限制,導致程式異常:問題是程式中有個靜態方法開啟檔案時忘記關閉。兩種解決方法,一是設定linux的最大檔案開啟數量(無法根本解決問題),二是解決程式中的bugs,即消除有問題的程式碼。 

第一次解決 
解決: 
方法一、增大系統開啟檔案的數量(無法根本解決問題)、 
   1、預設linux同時最大開啟檔案數量為1024個,用命令檢視如下:ulimit -a:檢視系統上受限資源的設定(open files (-n) 1024): 
 

Java程式碼 

 收藏程式碼

  1. [[email protected]**** 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  
    [
    [email protected]
    **** bin]#  


2、可以修改同時開啟檔案的最大數基本可以解決:ulimit -n 4096 

  1. [[email protected]**** bin]# ulimit -n 4096  
    [[email protected]**** 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  
    [[email protected]**** bin]#  


已經修改了最大開啟檔案數。 

方法二、修改程式中的bugs: 
程式中有個靜態的方法開啟檔案後,沒有關閉檔案,導致每次請求都會去開啟檔案,在程式中填入關閉輸入流的操作即可以: 

Java程式碼 

public static List<GpsPoint> getArrayList() throws IOException {  
  
        List<GpsPoint> pointList = ;  
        // 讀取配置檔案  
        InputStream in = ParseGpsFile.class.getClassLoader().getResourceAsStream("GPS1.TXT");  
          
        // 讀路徑出錯,換另一種方式讀取配置檔案  
        if ( == 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()) != ) {  
                  
                // 讀下一行資料,讀緯度  
                latude = br.readLine();  
                  
                if ( == latude) {  
                      
                    // 退出迴圈  
                    break;  
                }  
                  
                // 讀下一行資料,讀海拔  
                elevation = br.readLine();  
                if ( == latude) {  
                      
                    // 退出迴圈  
                    break;  
                }  
                  
                // 加入一個點  
                pointList.add(gps2point(longtude, latude, elevation));  
            }  
              
            in.close();  
            System.out.println("\n\n");  
        } catch (Exception e) {  
              
            in.close();  
            e.printStackTrace();  
        }  
          
        return pointList;  
    }  


問題徹底解決 

----- 
第二次解決: 
實際測試後發現這個問題還沒有解決,最終又找了些方法,經過一段時間的測試,似乎解決了問題: 

具體步驟如下: 
linux為redhat伺服器版本(非個人版),必須設定的內容: 

1、/etc/pam.d/login 新增 

  1. session required     /lib/security/pam_limits.so  


# 注意看這個檔案的註釋 
具體檔案的內容為: 

[[email protected]**** ~]# 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  


修改後的內容: 
 

bash: [[email protected]****: command not found  

[[email protected]**** ~]# clear  
[[email protected]**** ~]# 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  
  
[[email protected]**** ~]#  


2. /etc/security/limits.conf 新增 

root          –    nofile       1006154  
root 是一個使用者,如果是想所有使用者生效的話換成 * ,設定的數值與硬體配置有關,別設定太大了。 
修改前內容 

[[email protected]**** ~]# 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  
[[email protected]**** ~]#  
[[email protected]**** ~]# 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  
[[email protected]**** ~]#  


修改後的內容 


3. 修改 /etc/rc.local   新增 

echo 8061540 > /proc/sys/fs/file-max  


修改前內容 

  1. [[email protected]**** ~]# cat /proc/sys/fs/file-max  
    4096  
    [[email protected]**** ~]#  
    
    修改後內容 
  2. [[email protected]**** ~]# cat /proc/sys/fs/file-max  
    4096000  
    [[email protected]**** ~]#  
    
  3. 做完3個步驟,就可以了。 
    
    
    ************************************** 
    補充說明: 
    /proc/sys/fs/file-max 
    該檔案指定了可以分配的檔案控制代碼的最大數目。如果使用者得到的錯誤訊息宣告由於開啟檔案數已經達到了最大值,從而他們不能開啟更多檔案,則可能需要增加該值。可將這個值設定成有任意多個檔案,並且能通過將一個新數字值寫入該檔案來更改該值。 
    預設設定:4096 
    /proc/sys/fs/file-nr 
    該檔案與 file-max 相關,它有三個值: 
    已分配檔案控制代碼的數目 
    已使用檔案控制代碼的數目 
    檔案控制代碼的最大數目 
    該檔案是隻讀的,僅用於顯示資訊。 
    關於“開啟檔案數”限制 
    Linux系統上對每一個使用者可使用的系統資源都是有限制的,這是多使用者系統必然要採用的一種資源管理手段,試想假如沒有這種機制,那麼任何一個普通使用者寫一個死迴圈程式,用不了多久系統就要“拒絕服務”了。 
    今天我遇到了tomcat日誌報的錯誤資訊”too many open files”,第一意識就想到了是ulimit控制的”open files“限制。然而問題來了。我在/etc/profile里加入了 ulimit -n 4096儲存之後,普通使用者登入的時候均會收到一條錯誤資訊ulimit: open files: cannot modify limit: Operation not permitted。然後普通使用者的open files限制還是預設值1024。 
    然後開始在網際網路上搜索關於ulimit的資訊。網際網路果然方便,資訊鋪天蓋地。大家也可以搜一下試一下。其中我瞭解到兩個以前不知道的相關內容。 
    第一個是核心引數 fs.file-max  ,影射為 /proc/sys/fs/file-max 
    第二個是配置檔案 /etc/security/limits.conf 
    其中大部分的資訊中提到 將 /proc/sys/fs/file-max的值設定為4096和ulimit -n 4096是相同的效果。對此我很懷疑,為什麼呢?首先ulimit 是一個普通使用者也可以使用的命令,而fs.file-max只有root有權設定。其次,很明顯fs.file-max是一個全域性的設定,而ulimit 是一個區域性的設定,很明顯的是不相同的。 
    帶著疑慮,又在網上搜索了許久,未果(實際上是我搜索的關鍵字不夠準確)。 
    最後終於在核心文件/usr/src/linux/Documentation/sysctl/fs.txt裡找到下面一段話: 
    file-max & file-nr: 
    The kernel allocates file handles dynamically, but as yet it doesn’t free them again. The value in file-max denotes the maximum number of file-handles that the Linux kernel will allocate. When you get lots of error messages about running out of file handles, you might want to increase this limit. 
    The three values in file-nr denote the number of allocated file handles, the number of unused file handles and the maximum number of file handles. When the allocated file handles come close to the maximum, but the number of unused file handles is significantly greater than 0, you’ve encountered a peak in your usage of file handles and you don’t need to increase the maximum. 
    這兩段話的大致意思是: 
    核心動態地分配和釋放“file handles”(控制代碼)。file-max的值是核心所能分配到的最大控制代碼數。當你收到大量關於控制代碼用完的錯誤資訊時,你可以需要增加這個值以打破老的限制。 
    file-nr中的三個值的含意分別是:系統已經分配出去(正在使用)的控制代碼數,沒有用到的控制代碼數和所有分配到的最大控制代碼數。當分配出去的控制代碼數接近 最大控制代碼數,而“無用的控制代碼數”大於零時,表明你遇到了一個“控制代碼”使用高峰,這意為著你不需要增加file-max的值。 
    看完這段話,相信大家都明白了。file-max是系統全域性的可用控制代碼數。根據我後來又翻查的資訊,以及對多個系統的檢視求證,這個引數的預設值是跟記憶體大小有關係的,增加實體記憶體以後重啟機器,這個值會增大。大約1G記憶體10萬個控制代碼的線性關係。 
    再回過頭來看這兩段話,不知道你意識到了沒有,文中只提到了file-max的增加,而沒有提到了該值的減少。那些在操作ulimit時同時操 作了file-max的哥們兒,估計無一例外地將file-max設定成了4096或者2048。但以似乎也沒有因此而導致系統無法開啟檔案或者建議連 接。(實際上,我將file-max的值裝置成256,然後使用shell編寫用vi開啟500個檔案角本執行,並沒有得到任何錯誤資訊,檢視file- nr的值,系統當前分配的控制代碼值已經遠超過了後面的最大值。所以我猜想對於file-max的任何減少的操作都是毫無意義的,姑且不去管他。實踐中需要減 少file-max的時候總是不多見的。 )實事證明我犯了一個致命的錯誤。我測試的時候使用的是root使用者,而當我再次使用普通使用者測試的時候,預料中的錯誤資訊出現了:”Too many open files in system”。可見,file-max的減少對系統也是影響力的。前面的結論“所以我猜想對於file-max的任何減少的操作都是毫無意義的”是錯誤 的。 
    然後便是/etc/security/limits.conf檔案,這個檔案很簡單,一看就能明白。 
    於是我按照註釋中描述的格式兩個兩行: 
    *  soft  nofile  4096 
    *  hard  nofile  4096 
    恐怖的是,網上居然有人說改了這個設定是需要重啟系統的!實在是讓人想不通啊,鼎鼎大名的UNIX系統,怎麼可能因為這麼小小的一個改動就需要 重啟系統呢?結果當我再次以普通使用者登入的時候,那個”ulimit: open files: cannot modify limit: Operation not permitted”提示沒有了,檢視ulimit -n,果然已經變成了4096。 
    linux lsof 修改控制代碼限制(轉) 
    在Linux下,我們使用ulimit -n 命令可以看到單個程序能夠開啟的最大檔案控制代碼數量(socket連線也算在裡面)。系統預設值1024。 
    對於一般的應用來說(象Apache、系統程序)1024完全足夠使用。但是如何象squid、mysql、java等單程序處理大量請求的應用來說就有點捉襟見肘了。如果單個程序開啟的檔案控制代碼數量超過了系統定義的值,就會提到“too many files open”的錯誤提示。如何知道當前程序打開了多少個檔案控制代碼呢?下面一段小指令碼可以幫你檢視: 
    lsof -n |awk ‘{print $2}’|sort|uniq -c |sort -nr|more 
    在系統訪問高峰時間以root使用者執行上面的指令碼,可能出現的結果如下: 
    # lsof -n|awk ‘{print $2}’|sort|uniq -c |sort -nr|more 
    131 24204 
    57 24244 
    57 24231 
    56 24264 
    其中第一行是開啟的檔案控制代碼數量,第二行是程序號。得到程序號後,我們可以通過ps命令得到程序的詳細內容。 
    ps -aef|grep 24204 
    mysql 24204 24162 99 16:15 ? 00:24:25 /usr/sbin/mysqld 
    哦,原來是mysql程序開啟最多檔案控制代碼數量。但是他目前只打開了131個檔案控制代碼數量,遠遠底於系統預設值1024。 
    但是如果系統併發特別大,尤其是squid伺服器,很有可能會超過1024。這時候就必須要調整系統引數,以適應應用變化。Linux有硬性限制和軟性限制。可以通過ulimit來設定這兩個引數。方法如下,以root使用者執行以下命令: 
    ulimit -HSn 4096 
    以上命令中,H指定了硬性大小,S指定了軟性大小,n表示設定單個程序最大的開啟檔案控制代碼數量。個人覺得最好不要超過4096,畢竟開啟的檔案控制代碼數越多響應時間肯定會越慢。設定控制代碼數量後,系統重啟後,又會恢復預設值。如果想永久儲存下來,可以修改.bash_profile檔案,可以修改 /etc/profile 把上面命令加到最後。 
    
    
    
    仍未處理的問題: 
    為什麼redhat9的個人版按照以上的方式修改1024tcp連線限制依然不行呢? 
    是因為個人版最多支援1024個tcp連線,還是修改方式、相關檔案會有所不同? 
    
    以上內容,來源網路並加自己親自測試,經過測試,似乎沒有再出現過問題,但不知道是否真的解決,有待更長時間的測試看看 
    
    第三次解決--還解決不了,就徹底無語了(經過壓力測試,執行7天再也沒有出現該問題) 
    問題的原因是:原來的MINA2程式之關了IoSession,並沒有關閉IoConnector例項,但恰恰就是因為沒有關閉每次開啟的IoConnector例項,造成了"Too many open files ". 
    原來的程式: 
  1. /**  
  2.      * <pre><b>功能描述:</b>獲取非同步的session例項。  
  3.      *   
  4.      * @author :Kevin.xie  
  5.      * <b>建立日期 :</b>2011-9-15 上午10:06:27  
  6.      *  
  7.      * @return  
  8.      *  
  9.      * <b>修改歷史:</b>(修改人,修改時間,修改原因/內容)  
  10.      *  
  11.      * </pre>  
  12.      */    
  13.     public static IoSession getSession1() {    
  14.         // 建立客戶端聯結器    
  15.         IoConnector connector = new NioSocketConnector();    
  16.         // 設定事件處理器    
  17.         connector.setHandler(new WebClientHandler());    
  18.         // 設定編碼過濾器和按行讀取資料模式    
  19.         connector.getFilterChain()    
  20.                 .addLast("codec", new ProtocolCodecFilter(new ObdDemuxingProtocolCodecFactory(false)));    
  21.         // 建立連線    
  22.         ConnectFuture future = connector.connect(new InetSocketAddress(ServerConfigBoundle.getServerIp(),    
  23.                 ServerConfigBoundle.getServerPort()));    
  24.         // 等待連線建立完成    
  25.         future.awaitUninterruptibly();    
  26.         // 獲取連線會話    
  27.         IoSession session = future.getSession();    
  28.         return session;    
  29.     }    
  30.    /**  
  31.      * <pre><b>功能描述:</b>必須要關閉Connector和IoSession  
  32.      * @author :Kevin.xie  
  33.      * <b>建立日期 :</b>2011-10-20 上午10:20:54  
  34.      *  
  35.      * @param session 要關閉的session  
  36.      *  
  37.      * <b>修改歷史:</b>(修改人,修改時間,修改原因/內容)  
  38.      *  
  39.      * </pre>  
  40.      */    
  41.     public static void closeSession(IoSession session) {    
  42.         if (session !=  && !session.isClosing()) {    
  43.             // 沒有關閉,就關閉    
  44.             session.close(true);    
  45.             session = ;    
  46.         }    
  47.     }   


修改後的程式 

  1. /**  
  2.      *   
  3.      * <pre><b>功能描述:</b>獲取IoConnector和非同步的session例項  
  4.      * 無法關閉。特別的提醒,NioSocketConnector 也要關閉。  
  5.      * 函式名是 dispose()。這點特別重要。這次出現 too many open files 的問題根源在這裡  
  6.      *   
  7.      * @author :Kevin.xie  
  8.      * <b>建立日期 :</b>2011-9-15 上午10:06:27  
  9.      *  
  10.      * @return  
  11.      *  
  12.      * <b>修改歷史:</b>(修改人,修改時間,修改原因/內容)  
  13.      *  
  14.      * </pre>  
  15.      */    
  16.     public static Map<String, Object> getConnectorAndSession() {    
  17.         // 建立客戶端聯結器    
  18.         IoConnector connector = new NioSocketConnector();    
  19.         // 設定事件處理器    
  20.         connector.setHandler(new WebClientHandler());    
  21.         // 設定編碼過濾器和按行讀取資料模式    
  22.         connector.getFilterChain()    
  23.                 .addLast("codec", new ProtocolCodecFilter(new ObdDemuxingProtocolCodecFactory(false)));    
  24.         // 建立連線    
  25.         ConnectFuture future = connector.connect(new InetSocketAddress(ServerConfigBoundle.getServerIp(),    
  26.                 ServerConfigBoundle.getServerPort()));    
  27.         // 等待連線建立完成    
  28.         future.awaitUninterruptibly();    
  29.         // 獲取連線會話    
  30.         IoSession session = future.getSession();    
  31.         Map<String, Object> map = new HashMap<String, Object>();    
  32.         map.put(CONNECTOR_KEY, connector);    
  33.         map.put(SESSION_KEY, session);    
  34.         return map;    
  35.     }    
  36. /**  
  37.      *   
  38.      * <pre><b>功能描述:</b>必須要關閉Connector和IoSession  
  39.      * 特別的提醒,NioSocketConnector 也要關閉。  
  40.      * 函式名是 dispose()。這點特別重要。這次出現 too many open files 的問題根源在這裡  
  41.      * @author :Kevin.xie  
  42.      * <b>建立日期 :</b>2011-10-20 上午10:20:54  
  43.      *  
  44.      * @param connector 要關閉的IoConnector,不關閉會報 too many open files 錯誤  
  45.      * @param session 要關閉的session  
  46.      *  
  47.      * <b>修改歷史:</b>(修改人,修改時間,修改原因/內容)  
  48.      *  
  49.      * </pre>  
  50.      */    
  51.     public static void closeConnectorAndSession(IoConnector connector, IoSession session) {    
  52.         if (session !=  && !session.isClosing()) {    
  53.             // 沒有關閉,就關閉    
  54.             session.close(true);    
  55.             session = ;    
  56.         }    
  57.         if (connector !=  && !(connector.isDisposing() || connector.isDisposed())) {    
  58.             // 沒有關閉,就關閉    
  59.             connector.dispose();    
  60.             connector = ;    
  61.         }    
  62.     }    
  63. ]    



用完後一定要釋放資源: 

  1.  Map<String, Object> resultMap = SocketUtils.getConnectorAndSession();  
  2.   IoSession session = (IoSession) resultMap.get(SocketUtils.SESSION_KEY);  
  3.   IoConnector connector = (IoConnector) resultMap.get(SocketUtils.CONNECTOR_KEY);  
  4. ............  
  5. ............          
  6.   // 主動關閉連線  
  7.   SocketUtils.closeConnectorAndSession(connector, session);  



同時在配置檔案 /etc/security/limits.conf  加了一個配置(該不該問題不大): 
# kevin.xie added, fixed 'too many open file' bug', 2012-01-04 
* soft nofile 65536 
* hard nofile 65536 

  1. # 第二次解決新增的內容    
  2. # kevin.xie added, fixed 'too many open file' bug, limit open max files 1024, 2011-10-24    
  3. * - nofile 102400    
  4. # 第三次(本次)解決新增的問題(不過這個應該可以不修改,沒有印證,也懶得修改了)    
  5. # kevin.xie added, fixed 'too many open file' bug', 2012-01-04    
  6. * soft nofile 65536    
  7. * hard nofile 65536  

相關推薦

Linuxtomcatjava.net.SocketException: Too many open files”--MINA2 錯誤解決

轉載: 因為這個問題,我也是經過三次修改後,才徹底解決該問題。我是遇到了錯誤資訊:“Too many open files”和“No buffer space availabel”,從我的專案上看,兩個問題都是因為使用MINA2時,有些資源沒有關閉造成的。但是出現“To

解決Linuxjava.net.SocketException: Too many open files”異常

背景:專案上線後發現Telnet模組在穩定執行一段時間後會自動斷開,無法登陸,後臺丟擲:“java.net.SocketException: Too many open files”異常。環境: Java程式碼 Linux版本:cat /proc/version

在liunx經常出現java.net.SocketException: Too many open files錯誤是什麼原因

釋出在Tomcat+linux伺服器上的專案經常報”java.net.SocketException: Too many open files"的錯誤,根據錯誤分析如下 : Linux 系統預設的open files的設定是1024 通過 ulimit -a進行檢視。 core file size     

java.net.SocketException: Too many open files問題分析及解決方案

java web應用在執行一段時間之後出現了這麼個問題 java.net.SocketException: Too many open files at java.net.PlainSocketImpl.socketAccept(Native Method)

java.net.SocketException: Too many open files

原因: 作業系統的中開啟檔案的最大控制代碼數受限所致,常常發生在很多個併發使用者訪問伺服器的時候。因為為了執行每個使用者的應用伺服器都要載入很多檔案(new 一個socket 就需要一個檔案控制代碼),這就會導致開啟檔案的控制代碼的缺乏。 解決方式: a) 儘量把類打成

java.net.SocketException: Too many open files 解決辦法

一早起來,發現伺服器掛了,檢視日子,發現報了一推java.net.SocketException: Too many open files異常。搜尋後才知道,是linux系統對程序開啟的檔案數量是有限制的。 用命令ul

nginxaccept4() failed (23: Too many open files in system)

今天系統進不去了,用ssh連線伺服器也非常慢,負載均衡顯示後端連線異常,但是通過telnet命令檢視後端埠是正常的,用其他的伺服器telnet這臺伺服器的埠,不通,感覺很奇怪。 首先自己先寫了一個測試的頁面,開啟80埠,但是還是訪問出現問題,於是就查看了一下n

Linux關閉tomcatjava.net.ConnectException: Connection refused

Linux下關閉tomcat報錯,具體如下: Using CATALINA_BASE: /home/alpha/apache-tomcat-7.0.62 Using CATALINA_HOME: /home/alpha/apache-tomcat-7.0.62 Using CATALIN

eclipse裏啟動rabbitmq java.net.SocketException: Connection reset

soc IT 啟動 fcm csdn 測試 eml 下拉 == RabbitMQ學習之Java客戶端連接測試(二) https://blog.csdn.net/roc1029/article/details/51249412 使用guest用戶遠程連接RabbitMQ用戶名

Tomcat java.net.connectexception:拒絕連線 解決辦法

tomcat java.net.ConnectException: Connection refused 1,描述在一次配置新工程專案,修改Tomcat server.xml後,執行shutdow.sh指令碼關閉伺服器,提示出現如下錯誤:tomcat java.net.Co

啟動tomcat:java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory的解決

今天重新配置myeclipse8.5的tomcat時,啟動tomcat後報錯,java.lang.NoClassDefFoundError: org/apache/juli/logging/LogFactory 報這個錯說明你用的是tomcat7。 目前的MyEclip

Java--java.net.NoRouteToHostException: No route to host (Host unreachable) 解決

昨天在寫程式碼的時候偶然報了這個錯誤。百度了一下,並沒有適合我的答案(大部分都在說防火牆的問題,大家也可以先檢查一下防火牆是否關閉)。 後來我在仔細檢查程式碼中發現。 原來是我的程式碼中有一個bug。就是我會先檢查所有報錯節點的網路是否暢通,再檢查報錯節點的磁碟空間是不是

mina通訊,對於高併發的產生:java.io.IOException: Too many open files(開啟檔案控制代碼過多問題)

起因:由於業務系統有多個定時任務定時訪問銀行端,銀行每天也有大量業務訪問業務系統,都是通過mina通訊,部署在測試環境的系統每過一兩天開啟控制代碼過萬,生產的也是一週左右不重啟業務系統就會爆掉。一開始並不清楚到底是哪方面原因導致控制代碼增長這麼快,因為這是一個老系統,經過多次升級,大量的併發、多執行緒,所以只

【高併發】壓力測試 java.io.IOException: Too many open files解決方案

 對作業系統做相關的設定,增加最大檔案控制代碼數量。Linux在Linux核心2.4.x中需要修改原始碼,然後重新編譯核心才生效。編輯Linux核心原始碼中的 include/linux/fs.h檔案,將 NR_FILE 由8192改為65536,將NR_RESERVED_FILES 由10 改為 128。編

java.io.FileNotFoundException (Too many open files)

今天kafka叢集報錯,檢視日誌提示 [2018-07-18 17:34:02,672] ERROR Error while rolling log segment for PREPROCESS in dir /mnt/sdc (kafka.server.LogDirFai

高並發連接導致打開文件過多:java.io.IOException: Too many open files 解決方法

限制 security 打開文件 soft api too limit com inf 用 CentOS 做 API 接口服務器供其他終端調用時,並發量高會報錯:java.io.IOException: Too many open files。 其原因是在 Linux 下

tomcat啟動 java net BindException Permission denied null

                     1,啟動報錯顯示[org.springframework.web.servlet.DispatcherServlet]FrameworkServlet 'springMvc': initialization completed in 382 msJun 01, 201

tomcat啟動java.net.MalformedURLException: Local host name unknown

tomcat啟動報錯 Error: Exception thrown by the agent : java.net.MalformedURLException: Local host name unknown: java.net.UnknownHostException:

Hadoop格式化HDFSjava.net.UnknownHostException: centos64

save rect sys ges bsp mission compile 以及 msg 異常描述 在對HDFS格式化,執行hadoop namenode -format命令時,出現未知的主機名的問題,異常信息如下所示: Java代碼 [shirdrn@loc

Hadoop格式化HDFSjava.net.UnknownHostException: localhost.localdomain: localhost.localdomain

n-n article working boa att eth0 mini board title 異常描述 在對HDFS格式化,執行hadoop namenode -format命令時,出現未知的主機名的問題,異常信息如下所示: [plain] view pl