设为首页 收藏本站
查看: 1204|回复: 0

[经验分享] Apache NIO 框架 Mina 使用中出现 too many open files 问题的解决办法(转)

[复制链接]

尚未签到

发表于 2017-1-15 06:58:51 | 显示全部楼层 |阅读模式
最近一段时间在用 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, 开发团队也能很快回复。只是发现文档欠缺,例子都是“示意”,意思意思而已,不能直接用起来。上手有些门槛。

发表于 http://jacklondon.cnblogs.com,转载请注明出处。

-----------------
标签: NIO, Mina, socket leak
绿色通道:好文要顶关注我收藏该文与我联系
Jacklondon Chen
关注 - 0
粉丝 - 2
+加关注
1
0
(请您对文章做出评价)
« 博主前一篇:刚发布新的 web 单点登录系统,欢迎下载试用,欢迎提建议
» 博主后一篇:PostgreSQL 数据库在 Windows Server 2008 上安装注意事项
posted @ 2011-03-16 12:43 Jacklondon Chen 阅读(956) 评论(9) 编辑 收藏

评论
 回复 引用 查看   
#1楼2011-08-04 12:58 | zeitgeist      
博主好,
我遇到了与你相似问题,问题还没解决,
我想问下上面步骤c 中的代码是写在客户端的还是写在服务器端
 回复 引用 查看   
#2楼[楼主]2011-08-05 19:18 | Jacklondon Chen      
@zeitgeist
我这边代码都是服务器端代码,没有客户端代码。上面 h 提到NioSocketConnector.dispose(),我忘了写明在哪里调用,我会尽快更新补上。
不知道您的代码,是否也是类似于代理服务器。
 回复 引用 查看   
#3楼[楼主]2011-08-11 12:57 | Jacklondon Chen      
引用zeitgeist:
博主好,
我遇到了与你相似问题,问题还没解决,
我想问下上面步骤c 中的代码是写在客户端的还是写在服务器端

我这边是在 IoHandlerAdapter 子类中,关闭对应的 connector:
@Override
public void sessionClosed(IoSession session) throws Exception {
IoConnector con = (IoConnector) session.getAttribute(SsoMinaUtils.IO_SESSION_CONTEXT_KEY_IO_CONNECTOR);
SsoMinaUtils.closeQuietly(con);
 回复 引用 查看   
#4楼2011-08-12 22:42 | zeitgeist      
@Jacklondon Chen
博主你好
非常感谢你给的答复。我的服务现在暂时没有什么问题,但是我还是有2个 问题。
1 在你的文章中 h 步骤中提到的 NioSocketConnector也要关闭的,不知道你指的是在什么情况下关闭,肯定不是在IoSession关闭时关闭吧。
2 本人对Mina只是刚接触,对你说的代理服务器不是很清楚。我应该没用到。
我的服务大概是这样的
服务端:用来提供搜索服务,搜索功能依靠lucene.
客户端:tomcat服务器执行的代码作为客户端,发出搜索请求。
由于服务中其他模块的影响暂时只能将以上两部分放到同一个服务器上。
不知道这样的做法有什么缺陷,麻烦博主能够给出一些建议。
再次感谢能够博主热心回复。
 回复 引用 查看   
#5楼2011-08-19 10:37 | happyblue      
引用zeitgeist:
@Jacklondon Chen
博主你好
非常感谢你给的答复。我的服务现在暂时没有什么问题,但是我还是有2个 问题。
1 在你的文章中 h 步骤中提到的 NioSocketConnector也要关闭的,不知道你指的是在什么情况下关闭,肯定不是在IoSession关闭时关闭吧。
2 本人对Mina只是刚接触,对你说的代理服务器不是很清楚。我应该没用到。
我的服务大概是这样的
服务端:用来提供搜索服务,搜索功能依靠lucene.
客户端:tomcat服务器执行的代码作为客户端,发出搜索请求。
由于服务中其他模块的影响暂时只能将以上两部分放到同一个服务器上。
不知道这样...


NioSocketConnector关闭的问题主要出现在 你的服务器即作为Mina的服务端同时也作为mina的客户端跟其他服务打交道的时候
 回复 引用 查看   
#6楼[楼主]2011-08-19 13:32 | Jacklondon Chen      
引用zeitgeist:
@Jacklondon Chen
博主你好
非常感谢你给的答复。我的服务现在暂时没有什么问题,但是我还是有2个 问题。
1 在你的文章中 h 步骤中提到的 NioSocketConnector也要关闭的,不知道你指的是在什么情况下关闭,肯定不是在IoSession关闭时关闭吧。
2 本人对Mina只是刚接触,对你说的代理服务器不是很清楚。我应该没用到。
我的服务大概是这样的
服务端:用来提供搜索服务,搜索功能依靠lucene.
客户端:tomcat服务器执行的代码作为客户端,发出搜索请求。
由于服务中其他模块的影响暂时只能将以上两部分放到同一个服务器上。
不知道这样...

zeitgeist,如果你的服务器端只提供搜索服务,那么应该不需要用 mina.
不太清楚你所说的客户端用 tomcat 是什么架构。
据我个人理解,如果你的服务器端和客户端,都是用 tomcat ,那么这两个系统中,根本不需要做什么通讯。Web/HTTP 协议中,本来就可以在页面中链接来链接去的。
 回复 引用 查看   
#7楼2011-09-09 10:24 | zj6882917      
博主你好,很高兴看到你的这篇博文,我的项目也有这个问题,但是这个bug只有windows 2008上产生,在rh6.0上面是没有的。代码是相同的。
再有就是,我在开发环境中断住IoHandlerAdapter子类中的exceptionCaught和sessionIdle,在没有任何客户连入的情况下,依然会长时间产生多个127.0.0.1的本地连接,但是exceptionCaught和sessionIdle事件从来没有被触发过。所以我貌似没办法用你的办法修补我服务中的问题。
请博主指点迷津。
 回复 引用 查看   
#8楼[楼主]2011-09-09 22:08 | Jacklondon Chen      
引用zj6882917:
博主你好,很高兴看到你的这篇博文,我的项目也有这个问题,但是这个bug只有windows 2008上产生,在rh6.0上面是没有的。代码是相同的。
再有就是,我在开发环境中断住IoHandlerAdapter子类中的exceptionCaught和sessionIdle,在没有任何客户连入的情况下,依然会长时间产生多个127.0.0.1的本地连接,但是exceptionCaught和sessionIdle事件从来没有被触发过。所以我貌似没办法用你的办法修补我服务中的问题。
请博主指点迷津。

能略微透漏一下你用 mina 写什么样的程序么?代理服务器?socket 服务器?socket 客户端?
 回复 引用 查看   
#9楼2011-10-30 13:53 | zj6882917      
@Jacklondon Chen
引用Jacklondon Chen:
引用zj6882917:
博主你好,很高兴看到你的这篇博文,我的项目也有这个问题,但是这个bug只有windows 2008上产生,在rh6.0上面是没有的。代码是相同的。
再有就是,我在开发环境中断住IoHandlerAdapter子类中的exceptionCaught和sessionIdle,在没有任何客户连入的情况下,依然会长时间产生多个127.0.0.1的本地连接,但是exceptionCaught和sessionIdle事件从来没有被触发过。所以我貌似没办法用你的办法修补我服务中的问题。
请博主指点迷津。

能略微透漏一下你用...


感谢楼主关注我的恢复,我是用mina作socket服务器,在windows 2008下后非常多的本地端口连接本地端口的tcp连接,不知为何。
在rh6上面曾经发现过too many open files 问题,但是是因为我的代码问题,呵呵,有一路数据忘记close的缘故。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-328470-1-1.html 上篇帖子: CentOS6.3 x64+Nginx1.3.8/Apache-httpd 2.4.3+PHP5.4.8(php-fpm)+MySQL5.5.28+CoreSe 下篇帖子: 【端午节礼物大放送】深入解析Apache Mina源码(3)——Mina的线程池模型
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表