Mina 高并发短连接导致java.io.IOException: To

系统 1890 0

转自: http://xmdxzyf.iteye.com/blog/1698819

 

这几天在解决一个用mina开发的高并发通信过程中产生的一个bug。

   模拟场景为:

   通过定时触发启动线程模拟高并发短连接测试,测试的服务端有2个,一个是服务有起,一个没起,客户端和服务端均在同一服务器上。执行一段时间后linux主机上通过lsof命令查看,发现有递增的文件句柄,pipe和eventpoll。

   抛出的异常如下:

  

Java代码     收藏代码
  1. 2012 - 10 - 13   10 : 09 : 48  -org.apache.mina.core.service.SimpleIoProcessorPool.<init>(SimpleIoProcessorPool.java: 197 )  
  2.  Failed to create a  new  instance of org.apache.mina.transport.socket.nio.NioProcessor: null   
  3. java.lang.reflect.InvocationTargetException  
  4.         at sun.reflect.GeneratedConstructorAccessor110.newInstance(Unknown Source)  
  5.         at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java: 27 )  
  6.         at java.lang.reflect.Constructor.newInstance(Constructor.java: 513 )  
  7.         at org.apache.mina.core.service.SimpleIoProcessorPool.<init>(SimpleIoProcessorPool.java: 180 )  
  8.         at org.apache.mina.core.service.SimpleIoProcessorPool.<init>(SimpleIoProcessorPool.java: 112 )  
  9.         at org.apache.mina.core.polling.AbstractPollingIoConnector.<init>(AbstractPollingIoConnector.java: 93 )  
  10.         at org.apache.mina.transport.socket.nio.NioSocketConnector.<init>(NioSocketConnector.java: 56 )  
  11.         at com.develop.webplatform.funnel.client.JobClient.sendMessage(JobClient.java: 39 )  
  12.         at com.develop.webplatform.funnel.client.JobClient.sendJob(JobClient.java: 126 )  
  13.         at com.develop.webplatform.funnel.extend.JobExecRemotelyBySocket.execJobByTask(JobExecRemotelyBySocket.java: 66 )  
  14.         at com.develop.webplatform.funnel.JobManager.execJobByTask(JobManager.java: 27 )  
  15.         at com.develop.webplatform.quartz.job.TaskJob.executeInternal(TaskJob.java: 38 )  
  16.         at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java: 86 )  
  17.         at org.quartz.core.JobRunShell.run(JobRunShell.java: 223 )  
  18.         at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java: 549 )  
  19. Caused by: org.apache.mina.core.RuntimeIoException: Failed to open a selector.  
  20.         at org.apache.mina.transport.socket.nio.NioProcessor.<init>(NioProcessor.java: 61 )  
  21.         ...  15  more  
  22. Caused by: java.io.IOException: Too many open files  
  23.         at sun.nio.ch.IOUtil.initPipe(Native Method)  
  24.         at sun.nio.ch.EPollSelectorImpl.<init>(EPollSelectorImpl.java: 49 )  
  25.         at sun.nio.ch.EPollSelectorProvider.openSelector(EPollSelectorProvider.java: 18 )  
  26.         at java.nio.channels.Selector.open(Selector.java: 209 )  
  27.         at org.apache.mina.transport.socket.nio.NioProcessor.<init>(NioProcessor.java: 59 )  
  28.         ...  15  more  

    

    原代码中,关于客户端连接的代码如下:

   

Java代码     收藏代码
  1. final  NioSocketConnector connector =  new  NioSocketConnector();  
  2.          final  String[] result =  new  String[ 1 ];  
  3.         connector.getFilterChain().addLast( "codec" ,  
  4.                  new  ProtocolCodecFilter( new  ObjectSerializationCodecFactory()));  
  5.         connector.setHandler(handler);  
  6.   
  7.          //设置超时   
  8.         connector.setConnectTimeoutMillis(defaultConnectTimeOut);  
  9.         ConnectFuture connectFuture = connector.connect(address);  
  10.         connectFuture.awaitUninterruptibly();    //同步,等待,直到连接完成   
  11.          if  (connectFuture.isDone()) {  
  12.              if  (!connectFuture.isConnected()) {  //若在指定时间内没连接成功,则抛出异常   
  13.                 logger.info( "fail to connect "  + logInfo);  
  14.   
  15.                  throw   new  Exception();  
  16.             }  
  17.         }  

       

         经过分析,导致主机文件句柄泄露的原因为,客户端发起服务端连接时,会请求系统分配相关的文件句柄,在原代码中,仅仅判断是否连接成功,而未对连接失败进行资源释放,从而造成文件句柄泄露。当总的文件句柄数超过系统设置值(ulimit -n 查看同一个进程允许的最大文件句柄数),则抛出异常“java.io.IOException: Too many open files",导致无法创建新的连接,服务器挂掉。

      更改后的代码如下:

  

Java代码     收藏代码
  1. final  NioSocketConnector connector =  new  NioSocketConnector();  
  2.          final  String[] result =  new  String[ 1 ];  
  3.         connector.getFilterChain().addLast( "codec" ,  
  4.                  new  ProtocolCodecFilter( new  ObjectSerializationCodecFactory()));  
  5.         connector.setHandler(handler);  
  6.   
  7.          //设置超时   
  8.         connector.setConnectTimeoutMillis(defaultConnectTimeOut);  
  9.         ConnectFuture connectFuture = connector.connect(address);  
  10.         connectFuture.awaitUninterruptibly();    //同步,等待,直到连接完成   
  11.          if  (connectFuture.isDone()) {  
  12.              if  (!connectFuture.isConnected()) {  //若在指定时间内没连接成功,则抛出异常   
  13.                 logger.info( "fail to connect "  + logInfo);  
  14.                 connector.dispose();     //不关闭的话会运行一段时间后抛出,too many open files异常,导致无法连接   
  15.   
  16.                  throw   new  Exception();  
  17.             }  
  18.         }  

 

Mina 高并发短连接导致java.io.IOException: Too many open files解决方案


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论