做项目的时候,用到了mina框架,与server进行交互。由于采用的是短连接+心跳包+断线重连的方式,因此网络不稳定的时候经常会出现断线重连。

那么有时候偶尔会出现EMFILE: open too many files exception的问题,看堆栈信息是出在new socketconnector的时候。

Jacklondon Chen的一篇文章

Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法

http://www.cnblogs.com/jacklondon/archive/2011/03/16/1985926.html 提到了这个问题

最近一段时间在用 Apache NIO 框架 Mina, 用起来感觉不错。

我们使用 Apache NIO 作了一个 TCP server, 来处理 TCP 数据包。

只是最近突然发现 server 经常连接不上,每周一两次。用户没有进行屏幕截图就直接重新启动,没有找到第一手的故障现场资料。

开始以为是 JDK 及其他 Java 包 版本问题,连续升级了几次,问题依旧。

后来终于在客户现场抓个现行。屏幕截图、备份日志文件后,逐个 ping/telnet 各个服务器及其端口。发现都没有问题,奇怪了。突然想起,用 netstat 看看网络连接状态(windows server 2008), 发现大量的 127.0.0.1 到 127.0.0.1 的连接,状态为 ESTABLISHED , 端口看起来是逐步增加的。

再看日志文件,发现写出来的是 "too many open files” 导致 socket 连接不能建立。

网上搜索 google ,发现报告此问题的人不少,却没有人有解决方法。Apache Mina 网站上的 FAQ 也提到这个问题,说是要更改 windows 注册表,简直是胡扯。只能自己慢慢调查了。

这是一个类似于内存泄露的问题,只不过这里是 socket 未关闭导致。英文名词为 : “socket leak”。

经过几天的调试,发现了解决办法,特记录下来,供大家参考。

a. 使用到 NioSocketAcceptor 一个,用来 listen ,没有问题。

b. 自定义 IoHandlerAdapter 在 Mina 中是 Singleton, 只创建一次,也没有问题。

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. 因代码中使用了类似代理服务器的程序,需要特别处理。这里特别强调一下,Mina 自带的 proxy 程序没有实用价值。它使用的是多个客户端连接,服务器只用一个 NioSocketConnector 转发,这很成问题。如果 connector 断开了,岂不是影响很大?因此需要改成每个 客户端连接 对应一个 connector 的转发模式。

e. NioSocketConnector 并非 thread safe, 这点 Mina 文档中只字不提。很让人抓狂。

f. 系统中使用了以下 Mina NIO 的 Java 对象:

NioSocketAcceptor 用来 listen, 1个,配 1 个 IoHandlerAdapter

每次 1 客户 socket 连接,对应1 个 IoSession, 创建 1 个 NioSocketConnector 连接后端服务器,然后自动创建一个 IoSession 作为当前客户 socket 的 peer (同伴),也就是两个 IoSession 有对应关系。

g. 无论是客户 socket 连接的 IoSession 还是 peer IoSession , 在 sessionClosed 中需要调用 peer.close(false); 这里的 close(false) 不是立即关闭,而是让 peer 发完数据再关闭。这是由 NIO 这种异步操作特性决定的。这里不会造成死循环: client IoSession 调用 peer.close(false), 而 peer 反过来调用 client IoSession.close(false)。好像 Mina 做了特别处理。

h. 特别的提醒,NioSocketConnector 也要关闭。函数名是 dispose()。这点特别重要。这次出现 too many open files 的问题根源在这里。而 Mina 文档中只字不提。而 NioSocketConnector 与 peer IoSession 使用 127.0.0.1 端随机端口连接,匪夷所思。

而 peer IoSession 关闭后,没有关闭 NioSocketConnector , 也没有给它发 close event, 或者让它进入 exception, 这种设计也不好。 IoSession 关闭后,留着 NioSocketConnector 也是无用,还白白成了一个 ESTABLISHED 状态的连接,导致 socket leak。 这似乎就是所谓的半开 socket ? 还是觉得 Mina 这种设计不好。

上面写的是问题故障解决办法,特与大家分享。希望其它碰到此问题的人,少走点弯路。

最后总结,Mina 总体设计不错,代码质量也还好,我报告过一次 bug, 开发团队也能很快回复。只是发现文档欠缺,例子都是“示意”,意思意思而已,不能直接用起来。上手有些门槛。

重点是 h。原本重连的时候紧紧是new 一个connnector重连服务器,没有把之前的connector关闭,现在加上关闭connector,connector.dispose()会

阻塞线程,需要在线程中处理。

关于mina框架EMFILE: open too many files exception的处理的更多相关文章

  1. mina框架详解

     转:http://blog.csdn.net/w13770269691/article/details/8614584 mina框架详解 分类: web2013-02-26 17:13 12651人 ...

  2. GPS部标平台的架构设计(三) 基于struts+spring+hibernate+ibatis+quartz+mina框架开发GPS平台

    注意,此版本是2014年研发的基于Spring2.5和Struts2的版本,此版本的源码仍然销售,但已不再提供源码升级的服务,因为目前我们开发的主流新版本是2015-2016年近一年推出的基于spri ...

  3. 基于Java Mina框架的部标808服务器设计和开发

    在开发部标GPS平台中,部标808GPS服务器是系统的核心关键,决定了部标平台的稳定性和行那个.Linux服务器是首选,为了跨平台,开发语言选择Java自不待言. 我们为客户开发的部标服务器基于Min ...

  4. Android Mina框架的学习笔记

    Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络 ...

  5. 基于MINA框架快速开发网络应用程序

    1.MINA框架简介 MINA(Multipurpose Infrastructure for Network Applications)是用于开发高性能和高可用性的网络应用程序的基础框架.通过使用M ...

  6. 使用Mina框架开发 QQ Android 客户端

    Apache MINA是一个网络应用程序框架,用来帮助用户简单地开发高性能和高可靠性的网络应用程序.它提供了一个通过Java NIO在不同的传输例如TCP/IP和UDP/IP上抽象的事件驱动的异步AP ...

  7. Mina框架断包、粘包问题解决方式

    Mina框架断包.粘包问题解决方式 Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然.也能够提供JAVA 对象的序 ...

  8. Mina框架与Spring整合配置文件

    Mina框架与Spring的整合事实上非常easy,主要是要弄清楚要注入的属性的名称,进而选择合适的注入方法. 关于Spring的四种注入方法请还有一篇文章:spring依赖注入的四种方式 <? ...

  9. mina框架tcpt通讯接收数据断包粘包处理

    用mina做基于tcp,udp有通讯有段时间了,一直对编码解码不是很熟悉,这次做项目的时候碰到了断包情况,贴一下解决过程, 我接受数据格式如下图所示: unit32为c++中数据类型,代表4个字节,由 ...

随机推荐

  1. JQueryMobile + PhoneGap 经验总结

    1. pageinit & pageshow JQM的官方手册重点提醒了使用$(document).bind(‘pageinit’)代替$(document).ready(). 但当你需要对某 ...

  2. C++日志操作开源函数库之Google-glog

    今天想给我的C++项目找一个开源的日志类,用于记录系统日志,结果浪费了半个下午的时间.从网上搜索相关资料,找到以下几个备选方案: 1.log4cplus 下载地址:http://sourceforge ...

  3. IOS开发-cell的动态高度

    tableView中自定义cell的高度随子控件的内容动态变化,也是用的非常多的地方.现在就来处理一个自定义一个里面有文字(多少不定),图片(有无不定)的cell 首先要准备两个模型,一个是存放数据的 ...

  4. AngularJs中的服务

    一.angularJs中的简单服务应用 下面的例子让我们明白在AngularJs中如何去调用文件中的数据,从而将文件中的数据显示在页面上;改变url的地址,也可以去调用后台接口. 实例: <!D ...

  5. 提示“应用程序无法启动,因为应用程序的并行配置不正确”不能加载 System.Data.SQLite.dll

    新版本SQLITE,如果下载Precompiled Binaries版会出现提示“应用程序无法启动,因为应用程序的并行配置不正确”不能加载 System.Data.SQLite.dll. 下载Prec ...

  6. lucene.net helper类 【结合盘古分词进行搜索的小例子(分页功能)】

      转自:http://blog.csdn.net/pukuimin1226/article/details/17558247 添加:2013-12-25 更新:2013-12-26 新增分页功能. ...

  7. 使用Cyclone IV控制DDR2

    根据你的DDR2手册配置好megacore,megacore会生成一个example top: 在quartus中运行megacore生成的xxx_pin_assignments.tcl,指定DDR2 ...

  8. 【springmvc】之常用的注解

    原理这里不叙述,只讲怎么用 1. spring mvc中的@PathVariable是用来获得请求url中的动态参数的 @RequestMapping(value="/user/{userI ...

  9. 【solr】solr5.0整合tomcat

    1.下载 solr版本必须和lucene版本一致,这个链接http://archive.apache.org/dist/lucene/是apache子项目库,在这里可以下载lucene,我这里使用的是 ...

  10. 黄聪:禁止wordpress版本自动升级的解决方案

    在WordPress配置文件中找到wp-config.php,添加如下常量 define( 'AUTOMATIC_UPDATER_DISABLED', true );