关于mina框架EMFILE: open too many files exception的处理

做项目的时候,用到了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()会

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

时间: 2024-10-09 16:47:57

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

MINA框架

MINA 框架简介 Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(然,也可以提供JAVA 对象的序列化服务.虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能.高扩展性的网络通信应用,Mina 提供了事件驱动.异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型.Mina 主要有1.x 和2.x 两个分支,这里我们讲解最新版本2.0,如果你使用的是Mina 1.x,那么

Mina框架研究

Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架. 这个框架的优点: – 异步 – 无阻塞 – 事件驱动 – 支持TCP, UDP, APR, 串口- – 通过 过滤器(Filters)实现扩展性 – 同时提供协议框架 总体框架 之前的一个项目用到了MINA,最近想再系统的整理一下,主要参考MINA 2.0 User

长连接神器Mina框架的使用

前段时间学习了mina框架的使用.它是基于Socket进行通信,所以说在项目中要是需要长连接的使用,那mina框架是一个不错的选择. 下面简单介绍一下mina框架的使用,学习mina框架不长时间,现在写下来即时为了记录一下自己的学习经历,又希望可以帮助其他初学者朋友,若有不足与错误之处,还请大神指教. 在使用mina框架之前需要下载所需的jar包.可以在我的网盘中下载,Android端也可以用的.地址:http://pan.baidu.com/s/1skP8YT3 ,提取码:inyl. 所需的j

Android Mina框架的学习笔记

Apache MINA(Multipurpose Infrastructure for Network Applications) 是 Apache 组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架.当前发行的 MINA 版本支持基于 Java NIO 技术的 TCP/UDP 应用程序开发.串口通讯程序(只在最新的预览版中提供),MINA 所支持的功能也在进一步的扩展中.目前正在使用 MINA 的软件包括有:Apache Directory Project.Asyn

Mina框架项目运用

近期最一个项目对通信要求比較严格,须要建立长连接,且能处理多并发,所以选择了Mina框架.以下就简单记录开发的过程吧: mina 开发须要的jar包: mina pc端通信: 服务端: package cn.ys.net; import org.apache.mina.core.session.IoSession; import org.apache.mina.filter.codec.ProtocolCodecFactory; import org.apache.mina.filter.cod

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

1.MINA框架简介 MINA(Multipurpose Infrastructure for Network Applications)是用于开发高性能和高可用性的网络应用程序的基础框架.通过使用MINA框架可以可以省下处理底层I/O和线程并发等复杂工作,开发人员能够把更多的精力投入到业务设计和开发当中.MINA框架的应用比较广泛,应用的开源项目有Apache Directory.AsyncWeb.Apache Qpid.QuickFIX/J.Openfire.SubEthaSTMP.red5

使用Apache MINA框架搭建服务端

使用MINA框架搭建服务端步骤: 1.定义一个启动服务的类MinaServer,并实现接口ServletContextListener 2.定义一个处理业务逻辑的类MinaServerHandler,并继承类IoHandlerAdapter 类MinaServer代码例如以下: import java.net.InetSocketAddress; import javax.servlet.ServletContextEvent; import javax.servlet.ServletConte

Apache Mina框架实践

1.为什么要用Apache Mina框架 ApacheMina Server 是一个网络通信应用框架,Mina 可以帮助我们快速开发高性能.高扩展性的网络通信应用,Mina 提供了事件驱动.异步(Mina 的异步IO 默认使用的是JAVANIO 作为底层支持)操作的编程模型. 2.ApacheMina框架使用 Mina的执行流程: > IoService:这个接口在一个线程上负责套接字的建立,拥有自己的Selector,监听是否有连接被建立. > IoProcessor:这个接口在另一个线程上

Apache Mina框架自身实现的过滤器

在Apache Mina中,IoFilter介于IoService和IoHanlder之间,该IO过滤器对所有的输入.输出事件进行过滤,其在Apache Mina中的地位不可忽视,Apache Mina框架自身实现了很多过滤器,现将其作用总结一下: 1.BlacklistFilter:该过滤器称为黑名单过滤器,该过滤器用于阻止特定IP地址的访问Apache Mina服务端.其使用方法如下: private void addFilter(IoAcceptor acceptor) throws Un