Apache NIO 框架 Mina 使用中出现 too many open files 有关...
2019獨角獸企業(yè)重金招聘Python工程師標準>>>
時間: 2013-04-08 17:01:26.0
分類:? 軟件工程/管理 /? 開發(fā)方法 /? 文章 Apache NIO 框架 Mina 使用中出現(xiàn) too many open files 問題的解決辦法(轉(zhuǎn)) 最近一段時間在用 Apache NIO 框架 Mina, 用起來感覺不錯。?
我們使用 Apache NIO 作了一個 TCP server, 來處理 TCP 數(shù)據(jù)包。?
只是最近突然發(fā)現(xiàn) server 經(jīng)常連接不上,每周一兩次。用戶沒有進行屏幕截圖就直接重新啟動,沒有找到第一手的故障現(xiàn)場資料。?
開始以為是 JDK 及其他 Java 包 版本問題,連續(xù)升級了幾次,問題依舊。?
后來終于在客戶現(xiàn)場抓個現(xiàn)行。屏幕截圖、備份日志文件后,逐個 ping/telnet 各個服務器及其端口。發(fā)現(xiàn)都沒有問題,奇怪了。突然想起,用 netstat 看看網(wǎng)絡(luò)連接狀態(tài)(windows server 2008), 發(fā)現(xiàn)大量的 127.0.0.1 到 127.0.0.1 的連接,狀態(tài)為 ESTABLISHED , 端口看起來是逐步增加的。?
再看日志文件,發(fā)現(xiàn)寫出來的是 "too many open files” 導致 socket 連接不能建立。?
網(wǎng)上搜索 google ,發(fā)現(xiàn)報告此問題的人不少,卻沒有人有解決方法。Apache Mina 網(wǎng)站上的 FAQ 也提到這個問題,說是要更改 windows 注冊表,簡直是胡扯。只能自己慢慢調(diào)查了。?
這是一個類似于內(nèi)存泄露的問題,只不過這里是 socket 未關(guān)閉導致。英文名詞為 : “socket leak”。?
經(jīng)過幾天的調(diào)試,發(fā)現(xiàn)了解決辦法,特記錄下來,供大家參考。?
a. 使用到 NioSocketAcceptor 一個,用來 listen ,沒有問題。?
b. 自定義 IoHandlerAdapter 在 Mina 中是 Singleton, 只創(chuàng)建一次,也沒有問題。?
c. 自定義 IoHandlerAdapter 中需要有以下代碼:?
public void exceptionCaught(IoSession session, Throwable cause) throws Exception {?
??????? session.close(true);//force close right now?
}?
public void sessionOpened(IoSession session) throws Exception {?
??? session.getConfig().setBothIdleTime(180);//set timeout seconds, must?
}?
public void sessionIdle(IoSession session, IdleStatus status) throws Exception {?
??? session.close(true);//timeout now, close it?
}?
d. 因代碼中使用了類似代理服務器的程序,需要特別處理。這里特別強調(diào)一下,Mina 自帶的 proxy 程序沒有實用價值。它使用的是多個客戶端連接,服務器只用一個 NioSocketConnector 轉(zhuǎn)發(fā),這很成問題。如果 connector 斷開了,豈不是影響很大?因此需要改成每個 客戶端連接 對應一個 connector 的轉(zhuǎn)發(fā)模式。?
e. NioSocketConnector 并非 thread safe, 這點 Mina 文檔中只字不提。很讓人抓狂。?
f. 系統(tǒng)中使用了以下 Mina NIO 的 Java 對象:?
NioSocketAcceptor 用來 listen, 1個,配 1 個 IoHandlerAdapter?
每次 1 客戶 socket 連接,對應1 個 IoSession, 創(chuàng)建 1 個 NioSocketConnector 連接后端服務器,然后自動創(chuàng)建一個 IoSession 作為當前客戶 socket 的 peer (同伴),也就是兩個 IoSession 有對應關(guān)系。?
g. 無論是客戶 socket 連接的 IoSession 還是 peer IoSession , 在 sessionClosed 中需要調(diào)用 peer.close(false); 這里的 close(false) 不是立即關(guān)閉,而是讓 peer 發(fā)完數(shù)據(jù)再關(guān)閉。這是由 NIO 這種異步操作特性決定的。這里不會造成死循環(huán): client IoSession 調(diào)用 peer.close(false), 而 peer 反過來調(diào)用 client IoSession.close(false)。好像 Mina 做了特別處理。?
h. 特別的提醒,NioSocketConnector 也要關(guān)閉。函數(shù)名是 dispose()。這點特別重要。這次出現(xiàn) too many open files 的問題根源在這里。而 Mina 文檔中只字不提。而 NioSocketConnector 與 peer IoSession 使用 127.0.0.1 端隨機端口連接,匪夷所思。?
而 peer IoSession 關(guān)閉后,沒有關(guān)閉 NioSocketConnector , 也沒有給它發(fā) close event, 或者讓它進入 exception, 這種設(shè)計也不好。 IoSession 關(guān)閉后,留著 NioSocketConnector 也是無用,還白白成了一個 ESTABLISHED 狀態(tài)的連接,導致 socket leak。 這似乎就是所謂的半開 socket ? 還是覺得 Mina 這種設(shè)計不好。?
上面寫的是問題故障解決辦法,特與大家分享。希望其它碰到此問題的人,少走點彎路。?
最后總結(jié),Mina 總體設(shè)計不錯,代碼質(zhì)量也還好,我報告過一次 bug, 開發(fā)團隊也能很快回復。只是發(fā)現(xiàn)文檔欠缺,例子都是“示意”,意思意思而已,不能直接用起來。上手有些門檻。? 
轉(zhuǎn)載于:https://my.oschina.net/handsomeban/blog/132143
總結(jié)
以上是生活随笔為你收集整理的Apache NIO 框架 Mina 使用中出现 too many open files 有关...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Hive Performance 学习
 - 下一篇: shell命令小记