轉(zhuǎn)自: http://xmdxzyf.iteye.com/blog/1698819
?
這幾天在解決一個(gè)用mina開(kāi)發(fā)的高并發(fā)通信過(guò)程中產(chǎn)生的一個(gè)bug。
?? 模擬場(chǎng)景為:
?? 通過(guò)定時(shí)觸發(fā)啟動(dòng)線程模擬高并發(fā)短連接測(cè)試,測(cè)試的服務(wù)端有2個(gè),一個(gè)是服務(wù)有起,一個(gè)沒(méi)起,客戶端和服務(wù)端均在同一服務(wù)器上。執(zhí)行一段時(shí)間后linux主機(jī)上通過(guò)lsof命令查看,發(fā)現(xiàn)有遞增的文件句柄,pipe和eventpoll。
?? 拋出的異常如下:
??
- 2012 - 10 - 13 ? 10 : 09 : 48 ?-org.apache.mina.core.service.SimpleIoProcessorPool.<init>(SimpleIoProcessorPool.java: 197 )??
- ?Failed?to?create?a? new ?instance?of?org.apache.mina.transport.socket.nio.NioProcessor: null ??
- java.lang.reflect.InvocationTargetException??
- ????????at?sun.reflect.GeneratedConstructorAccessor110.newInstance(Unknown?Source)??
- ????????at?sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java: 27 )??
- ????????at?java.lang.reflect.Constructor.newInstance(Constructor.java: 513 )??
- ????????at?org.apache.mina.core.service.SimpleIoProcessorPool.<init>(SimpleIoProcessorPool.java: 180 )??
- ????????at?org.apache.mina.core.service.SimpleIoProcessorPool.<init>(SimpleIoProcessorPool.java: 112 )??
- ????????at?org.apache.mina.core.polling.AbstractPollingIoConnector.<init>(AbstractPollingIoConnector.java: 93 )??
- ????????at?org.apache.mina.transport.socket.nio.NioSocketConnector.<init>(NioSocketConnector.java: 56 )??
- ????????at?com.develop.webplatform.funnel.client.JobClient.sendMessage(JobClient.java: 39 )??
- ????????at?com.develop.webplatform.funnel.client.JobClient.sendJob(JobClient.java: 126 )??
- ????????at?com.develop.webplatform.funnel.extend.JobExecRemotelyBySocket.execJobByTask(JobExecRemotelyBySocket.java: 66 )??
- ????????at?com.develop.webplatform.funnel.JobManager.execJobByTask(JobManager.java: 27 )??
- ????????at?com.develop.webplatform.quartz.job.TaskJob.executeInternal(TaskJob.java: 38 )??
- ????????at?org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java: 86 )??
- ????????at?org.quartz.core.JobRunShell.run(JobRunShell.java: 223 )??
- ????????at?org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java: 549 )??
- Caused?by:?org.apache.mina.core.RuntimeIoException:?Failed?to?open?a?selector.??
- ????????at?org.apache.mina.transport.socket.nio.NioProcessor.<init>(NioProcessor.java: 61 )??
- ????????...? 15 ?more??
- Caused?by:?java.io.IOException:?Too?many?open?files??
- ????????at?sun.nio.ch.IOUtil.initPipe(Native?Method)??
- ????????at?sun.nio.ch.EPollSelectorImpl.<init>(EPollSelectorImpl.java: 49 )??
- ????????at?sun.nio.ch.EPollSelectorProvider.openSelector(EPollSelectorProvider.java: 18 )??
- ????????at?java.nio.channels.Selector.open(Selector.java: 209 )??
- ????????at?org.apache.mina.transport.socket.nio.NioProcessor.<init>(NioProcessor.java: 59 )??
- ????????...? 15 ?more??
????
??? 原代碼中,關(guān)于客戶端連接的代碼如下:
???
- final ?NioSocketConnector?connector?=? new ?NioSocketConnector();??
- ???????? final ?String[]?result?=? new ?String[ 1 ];??
- ????????connector.getFilterChain().addLast( "codec" ,??
- ???????????????? new ?ProtocolCodecFilter( new ?ObjectSerializationCodecFactory()));??
- ????????connector.setHandler(handler);??
- ??
- ???????? //設(shè)置超時(shí) ??
- ????????connector.setConnectTimeoutMillis(defaultConnectTimeOut);??
- ????????ConnectFuture?connectFuture?=?connector.connect(address);??
- ????????connectFuture.awaitUninterruptibly();??? //同步,等待,直到連接完成 ??
- ???????? if ?(connectFuture.isDone())?{??
- ???????????? if ?(!connectFuture.isConnected())?{? //若在指定時(shí)間內(nèi)沒(méi)連接成功,則拋出異常 ??
- ????????????????logger.info( "fail?to?connect?" ?+?logInfo);??
- ??
- ???????????????? throw ? new ?Exception();??
- ????????????}??
- ????????}??
???????
???????? 經(jīng)過(guò)分析,導(dǎo)致主機(jī)文件句柄泄露的原因?yàn)?,客戶端發(fā)起服務(wù)端連接時(shí),會(huì)請(qǐng)求系統(tǒng)分配相關(guān)的文件句柄,在原代碼中,僅僅判斷是否連接成功,而未對(duì)連接失敗進(jìn)行資源釋放,從而造成文件句柄泄露。當(dāng)總的文件句柄數(shù)超過(guò)系統(tǒng)設(shè)置值(ulimit -n 查看同一個(gè)進(jìn)程允許的最大文件句柄數(shù)),則拋出異常“java.io.IOException: Too many open files",導(dǎo)致無(wú)法創(chuàng)建新的連接,服務(wù)器掛掉。
????? 更改后的代碼如下:
??
- final ?NioSocketConnector?connector?=? new ?NioSocketConnector();??
- ???????? final ?String[]?result?=? new ?String[ 1 ];??
- ????????connector.getFilterChain().addLast( "codec" ,??
- ???????????????? new ?ProtocolCodecFilter( new ?ObjectSerializationCodecFactory()));??
- ????????connector.setHandler(handler);??
- ??
- ???????? //設(shè)置超時(shí) ??
- ????????connector.setConnectTimeoutMillis(defaultConnectTimeOut);??
- ????????ConnectFuture?connectFuture?=?connector.connect(address);??
- ????????connectFuture.awaitUninterruptibly();??? //同步,等待,直到連接完成 ??
- ???????? if ?(connectFuture.isDone())?{??
- ???????????? if ?(!connectFuture.isConnected())?{? //若在指定時(shí)間內(nèi)沒(méi)連接成功,則拋出異常 ??
- ????????????????logger.info( "fail?to?connect?" ?+?logInfo);??
- ????????????????connector.dispose();???? //不關(guān)閉的話會(huì)運(yùn)行一段時(shí)間后拋出,too?many?open?files異常,導(dǎo)致無(wú)法連接 ??
- ??
- ???????????????? throw ? new ?Exception();??
- ????????????}??
- ????????}??
?
Mina 高并發(fā)短連接導(dǎo)致java.io.IOException: Too many open files解決方案
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
