`
xnxqs
  • 浏览: 12284 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
社区版块
存档分类
最新评论

MINA使用心得及相关要点,有一个bug的解决方案,不知道其它朋友是否遇到过(二)

    博客分类:
  • mina
阅读更多

 

IoBuffer 接口

IoBuffer MINA 中的独有接口,主要继承实现的是 java NIO 中的 ByteBuffer ,所以从使用方法上来看二者区别不大,唯一比较大的区别就是, IoBuffer 支持可变长的数据填充,对于这个类有三个关键属性,分别是

capacity( 容量 ) 是它所包含的元素的数量。缓冲区的容量不能为负并且不能更改。 limit( 限制 )      是第一个不应该读取或写入的元素的索引。

position ( 位置 )    是下一个要读取或写入的元素的索引。

以上三个属性的值都不能为负,其关系遵守以下不变式:

            0<= 位置 <= 限制 <= 容量

在这里还要郑重的介绍三个方法分别是:

clear() : 使缓冲区为一系列新的通道读取或相对放置 操作做好准备:它将限制设置为容量大小,将位置设置为 0

flip() : 使缓冲区为一系列新的通道写入或相对获取 操作做好准备:它将限制设置为当前位置,然后将位置设置为 0

rewind() : 使缓冲区为重新读取已包含的数据做好准备:它使限制保持不变,将位置设置为 0

从本质上讲这三个方法都是对之前所介绍的三个属性进行操作,所以这里就会有一个误区,很多人从字面上解读 clear() 这个方法,以为这个方法就是将数据擦除。而实际上 clear 方法并不有擦除数据,仅仅是做了二件事,一是将 limit=capacity, 二是 position=0 ,这使得数据好像被清除,以便接收下一次的读写。但请大家千万注意 ,在写自定义解(编)码器时一定不要随便使用这些方法,请确保在对这些方法有了足够的认识后(最好的方法就是解读源码),才去使用它。特别是直接使用 clear() 时,一旦使用不当,在截取数据非常容易发生死循环的情况,因为前面已经说过, clear 并不是清除数据,而只是改变属性值,也就是说原数据依旧保留,这会导致某些时候会不停的重置这三个属性,去读同一段索引的数据,从而导致死循环。网上好多 demo 都是直接使用的 clear() ,其实都是存在一定隐患的,希望能看到这里的朋友能引起警惕 , 个人认为最好的清除方式就是人为的控制 Iobuffer 的三个属性值。 以下是参考代码 :

 

        int oldPos = in.position();

      int oldLimit = in.limit();

    ....... 开始 ..........

    处理数据

    ....... 结束 ..........

        int pos = in.position();

        in.limit(oldLimit);

    in.position(pos);

注: 以上代码仅适用于一次读取不完,需要从iobuffer 中多次读取的情况,具体情况请具体对待,核心思想就是操作iobuffer 的三个属性。

sendUrgentData() 方法的使用

这个方法的作用,只要是用过 socket 编程的童鞋都知道它的作用。没错,它就是通过发送一个紧急字符到服务端 (对 socket 来说实际上并不存在严格意义上的客户端或服务端,谁主动谁就是客户端) ,用来测试连接是否保持的一个方法。使用这个方法有二个限制。一是必须对方的 OS 支持该方法,二是要求服务端的 SO_OOBINLINE false. 否则 服务 端将会把这个紧急字符认为是正常报文一并接收,而不是抛弃。反之当 SO_OOBINLINE true 时,这个紧急字符仅仅用来确认通讯是否正常之用,服务端接收后会立刻抛弃不予处理的。默认情况下 SO_OOBINLINE 的值就是 false, 所以一般情况下,客户端直接用这个方法就可以测试连接是否保持了。

按理来说这个默认设置是个好事,但在笔者的项目开发中曾经因为这个 sendUrgentData () 被困扰了近一周的时间。事情的起因要从性能测试开始说起。

测试人员在测试过程中发现当前置机启动后有连接产生时就会让 CPU 占用率高居不下,开始笔者不是很在意,认为这个时间里有 IO 操作, CPU 高居不下很正常,后来进一步测试发生在没有数据发送的情况下 CPU 也会占到近 50% 左右,这个现象就很不正常了,于是折腾开始。

先是确认前置机的哪个部分会占用 cpu, 很快将目标锁定到了调度机,接下来对调度机进行代码排查,没有发生任何问题,头大了,再次进入 QQ 群讨论该问题,有人向我推荐了 JRMC (这也是我要向大家强烈推荐该工具的原因,网络的力量是强大的!!!嘿嘿。。。),通过这个监视工具,本人很快就再次缩小目标,将目标定位到一个叫 Ioprocesse-1 的线程上面,从名字及本文之前介绍的内容来看,很明显这个 MINA 框架内部线程导致的,随后就到网上查找是否有同类的现象,很遗憾本人可能是遇到一个前所未有的问题了,网络上提到使用 MINA 导致 CPU 占用率过高的内容几乎没有,无奈之下本人试着换 JDK 版本、 MINA 版本、甚至改写 MINA 源代码,一番折腾下来,结果是统统做了无用功。因为这个问题暂时不会影响测试和使用再加上时间过紧,后来就暂时将这个问题搁置了起来。某天,在开发的过程中笔者忽然想到:前置机的三个部分都是独立程序,通信机的接口也都是用 mina 改写的,为什么终端与通讯机没有这种现象发生呢?一番推理之下,本人反而将目标锁定到了占用率正常的通机机上面了,通过反复的排查,最终将问题锁定到了方法级,那就是 sendUrgentData 这个罪魁祸首。

本人试验发现,只要没有调用 sendUrgentData 方法所有一切都很正常, 但通信机 一旦调用 sendUrgentData 方法用来测试与调度机是否保持通信时,就会让调度机的 CPU 占用率瞬间飙升。但一个通信程序测试连接的方法是必不可少,而且暂时没有更好的能代替 sendUrgentData 的方法,所以就想着去改造 sendUrgentData 的源代码,结果一番跟踪下来才傻了眼,原来 sendUrgentData 方法 的底层实现是 native 类型( 注三 )根本就无从改起,最终本人将注意打到了调度机的解码器上面。代码比较多笔者就不帖了,只写上具体的解决步骤,有实际需求的,欢迎讨论。

步骤:

1 、在客户端(本例中客户端为通讯机)使用 sendUrgentData ()方法时,请设置一个报      中不可能出现的数字,本案例中使用的是 -16

2、  在服务端的处理类(即实现 IoHandlerAdapter 的类,为必须类)的 sessionCreated 方法内设置 SO_OOBINLINE true. 代码如下:

  @Override

       public void sessionCreated(IoSession session) throws Exception {

              IoSessionConfig cfg = session.getConfig();

                if (cfg instanceof SocketSessionConfig) {

                 ((SocketSessionConfig) cfg).setOobInline( true );

                }

       }

3、  在服务端的解码器中将接受到的 -16 的字符全部手动抛弃(注意 IoBuff 三属性的重新设定)。

至此问题解决,但从解决方法来看,这个方法并不具有代表性,当碰到以下情况是并不一定适用:

情况一: 报文的内容本身有可能无所不包,那么 sendUrgentData 设置什么好呢??

情况二: 客户端的程序无法改动时,又该如何应对呢??

当然这个问题的终结解决方案并不在本文的讨论范围之类,这个很明显就是 mina 的一个 BUG ,不知道 2.04 的版本有没有解决这个问题,但从官网所贴的问题列表来看,这个 BUG 应该是依旧存在的,奈何笔者 E 文比较烂,看看资料还可以,要我动手写,并将以上内容用 E 文表达出来,确实是没有那个勇气的,希望能看到这一段的童鞋能代劳一、二,督促官方早日改好这个 BUG ,咱也算是为开源软件尽了一份力不是? ^_^

有的童鞋看到这里可能会说笔者是不是太啰嗦了,几句话可以解决的事情讲这么多,这里我想强调一下的是,本文 的核心内容 主要讲的还是使用心得, 不是使用方法,在这里之所以把 解决 过程讲得这么详细,还是希望达成二点目的。

1 、笔者希望通过对过程详细的描述,来提醒大家。做咱们这一行的不可能不遇到问题,但遇到问题首要的是先缩小范围,再确定范围,实际确定不下来的,不妨跟同行讨论一番,如果还确定不下来,咱就暂时放一放,等脑子静下来以后,把思路跳出来,反向追踪,说不定问题的表象并不是问题发生的缘原呢?(这话有点拗口,不做解释。。。。   -_-!! )在本文中就是一个很明显的例子,明明是调度机表现出来的 CPU 占用过高,但导致这一现象发生的却是在通讯机上了。

2 、再次推荐 JRMC, 这东西真的很好用。独乐乐不如众乐乐~~   什么?你已经知道了?知道了,你怎么不告诉我?你真是坏啊。。。。。。哦 ~ 漏说了一句 , 这个工具是 Oracle JRockit JDK 自带的,据说这个 JDK 的效率能比普通 JDK 的效率高上 2%-10% 非常适合在生产环境下使用。 什么??你还是知道了?? 你,你,你。。。。。。(吐血 ing....

当然了,群众的力量是无穷的,大家嫌我太罗嗦的话,下面的内容我就简单一点吧。

 

注三: 所谓的 native 类型的方法,是 JAVA 中的一种特殊方法,凡是标注这个关键字的方法,其本身并没有任何实现代码,最终的运行都是通过虚拟机调用 OS 的底层的方法来运行的。

Concurrent 包下的一些类

这里主要推荐二个集合类,分别是 ConcurrentLinkedQueue ConcurrentHashMap 这二个类的使用基本上不需要你考虑是不是多线程的编程,也不需要用锁,可以大幅提高并发量过大时的对像存取,至于实现机制劳驾大家自己去 GOOGLE 一把吧。

结尾语

文章到这里基本上算是结束了,而项目最终的并发量从 2680 提升至 3.5W, 客户要求的是 2W 的并发量,所以后面更高的并发没有继续再测,至本文截稿为止,最新的消息是项目的一期工作已经顺利通过了国家级机构的评测。但实质上本文关于 MINA 框架还有很多东西没有涉及到,比如说与 Spring 的结合,对 Jmx 的支持,自定义协议详细举例等等,但我想这点小困难应该不会妨碍大家对 mina 的学习热情吧!感兴趣的童鞋不妨把它当成一个课后作业来做做吧 !!  ^_^

分享到:
评论
5 楼 弃天笑 2011-08-09  
按照楼主说的,直接设置参数,没有跟Hadler另外线程了
但是这样做的话,有一个问题,感觉好像用不尽cpu,cpu20%左右,mina就处理数据不过来了
不过我会做下一步测试看看
4 楼 弃天笑 2011-07-29  
嗯,多谢楼主回复
1.按照你说的
NioSocketAcceptor acceptor = new NioSocketAcceptor(5 or 9);
这样设置的话,是不是IoHandlerAdapter就不需要另外设置线程了。直接接受到数据之后,就在当前线程上进行处理

关于IoHandlerAdapter,我在一些网上文章里提到,说最好是IoHandlerAdapter用另外线程来处理,这样的话,就不会占用mina解析网络数据流的线程
//给IoHander增加独立的操作线程,与IO的线程独立开来
filterChain.addLast("IoHandlerThread", new ExecutorFilter(Executors.newScheduledThreadPool(5/9))); 

这样的设置的话,触发IoHandlerAdapter方法的时候,就是新的线程了。
我目前是这样做的。在NioSocketAcceptor 这里没有设置好,造成接受客户端数据的时候cpu比较高。等一下试一下修改参数。然后再做一下测试看效果怎样
(这里问一下,不知道楼主有没有给IoHandlerAdapter另外设置线程池)

关于BUFFERsize
我设得比较大,这样在压测量很大的时候,就会出现一些请求很久才有回应。但是就不会造成mina卡住。(我设置成16 * 1024 * 1024)

3 楼 xnxqs 2011-07-22  
打错了。应该是
NioSocketAcceptor acceptor = new NioSocketAcceptor(5 or 9);
2 楼 xnxqs 2011-07-22  
1.官方推荐的是N+1,N是CPU的核心数。如果你的四颗CPU都是双核的,就是8+1,如果是单核的,就是4+1.
所以
NioSocketAcceptor acceptor = new NioSocketAcceptor(4/8);


2,你设置好上面的,就不用管这个东西是由多少个线程来处理了。可能你的理解上有点误差,IoHandlerAdapter这个有多少个线程来处理,不是设定的,而是根据请求及具体情况来确定的。

3.BUFFERsize的设置根据你自己的需要随便设,我个人比较懒,喜欢一次性传很长的报文,一般来说,你只要不是通过他传文件,设成1024*1024绝对足够了,里面的单位是以字节为单位的,1024*1024就是一M了。我的项目中只设了10*1024,黙认情况下,它的大小是8*1024
1 楼 弃天笑 2011-07-22  
在一台4颗的服务器配置上跑的mina服务端
1.mina服务器的参数需要怎么设置呢?
例如服务端的NioSocketAcceptor acceptor = new NioSocketAcceptor();
我看到你的教程里是可以设置参数的,这个需要怎样设置?
IoHandlerAdapter需要多少个线程处理会比较好呢?
MaxReadBufferSize需要设置多大?我现在是 16* 1024

相关推荐

    Android2.2配合Mina时,出现的问题及完美解决方案

    在Android开发过程中,有时我们需要利用网络通信框架进行服务器与客户端之间的数据交互,Mina就是其中的一个优秀选择。本文将深入探讨在Android 2.2版本上集成Mina框架时可能出现的问题,以及如何找到这些问题的完美...

    mina的高级使用,mina文件图片传送,mina发送文件,mina报文处理,mina发送xml和json

    Apache Mina是一个开源的网络通信应用框架,主要应用于Java平台,它为高性能、高可用性的网络应用程序提供了基础架构。在本文中,我们将深入探讨Mina的高级使用,特别是在文件图片传送、文件发送、XML和JSON报文处理...

    mina框架的使用

    Apache MINA(Multipurpose Infrastructure for Network Applications)是一个Java框架,主要设计用于简化网络应用程序的开发,尤其是TCP/IP和UDP协议的应用。MINA 提供了一种高级的、高性能的、异步事件驱动的网络...

    MINA断线重连死锁解决

    在IT行业中,网络通信是不可或缺的一部分,而Apache MINA(Model-Independent Network Application Framework)是一个高性能、异步的网络应用程序框架,广泛应用于TCP/IP和UDP协议的开发。当我们遇到"MINA断线重连...

    mina使用例子

    Apache Mina是一个开源项目,它提供了一个高度可扩展和高性能的网络通信框架。这个框架主要用于构建网络应用,如服务器和客户端,支持多种协议,包括TCP、UDP和HTTP等。Mina的目标是简化网络编程,让开发者能够专注...

    mina使用mina使用mina使用

    通过以上介绍,我们可以看出,Mina是一个强大的工具,尤其对于那些需要处理大量并发连接并进行复杂数据交换的网络应用程序来说,它提供了一种高效且易于管理的解决方案。在实际开发中,掌握Mina的使用能有效提升项目...

    MINA使用札记(CumulativeProtocolDecoder使用)

    《MINA使用札记——CumulativeProtocolDecoder使用详解》 MINA(Java Multithreaded Network Application Framework)是一个强大的、高性能的Java网络应用框架,它主要用于构建可伸缩的、高性能的服务端应用,如...

    apache-mina-2.0.4.rar_apache mina_mina

    Apache Mina是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个"apache-mina-2.0.4.rar"压缩包包含的是Apache Mina 2.0.4版本的源代码,是深入理解和定制Mina的...

    Android平台MINA框架使用详细解析

    在Android平台上,MINA(Java Miniature Network Application Framework)是一个高度可扩展的网络应用程序框架,主要用作构建高性能、高效率的服务端和客户端应用程序。它提供了丰富的网络通信API,支持TCP/IP和UDP/...

    一个Apache MINA使用案例源代码ApacheMina

    总结来说,Apache MINA是一个强大的网络编程框架,它在Android开发中虽然不常用,但其高效和灵活的特性使其在特定场景下有其价值。通过深入研究提供的源代码,你可以更深入地理解MINA的工作原理,并学习如何在...

    Mina+Socket通信

    总的来说,Mina与Socket结合使用,可以构建出高效、灵活的网络通信解决方案。Mina的高级抽象简化了网络编程的复杂性,而Socket则提供了基础的网络通信能力。理解这两者的原理和用法,对于提升Java网络编程技能至关...

    Apache MINA框架相关资料

    Apache MINA(Multipurpose Infrastructure for Network Applications)是一个高性能、异步事件驱动的网络应用程序框架,主要用于简化开发高质量的网络服务。这个框架适用于多种协议,如TCP/IP和UDP/IP,以及NIO(非...

    mina即时聊天demo

    **mina即时聊天demo** Mina(Java Multithreaded Application Network Architecture)是一个开源的网络通信框架,由Apache软件...无论是即时聊天系统,还是其他基于网络的项目,Mina都能提供高效、可靠的解决方案。

    MinaServer for Android

    总的来说,MinaServer为Android开发者提供了一种在移动设备上搭建服务端应用的解决方案,利用Apache Mina的强大功能,可以轻松处理网络通信任务。对于希望扩展Android应用功能或构建分布式系统的开发者来说,这是一...

    Mina使用详细教程

    Mina使用详细教程,这里有详细步骤,和netty是一个母亲

    MINA 2.0.0-M6

    总的来说,MINA 2.0.0-M6作为MINA框架的一个重要里程碑,旨在提供更稳定、更高效的网络通信解决方案。开发者可以通过升级到这个版本,利用其新特性并提高应用性能。同时,通过阅读源码和文档,可以深入理解MINA的...

    MINA_API+MINA_DOC+mina

    MINA (Java IO Network Application Framework) 是一个由Apache软件基金会开发的开源网络通信框架,主要应用于构建高性能、高可用性的网络服务器。这个压缩包包含了MINA API文档、自学手册以及开发指南,对于学习和...

    一个应用mina的实例(源码)

    Apache Mina是一个开源项目,它提供了一个高度可扩展和高性能的网络通信框架。这个实例是基于Mina框架构建的一个应用程序,名为"BTUSimulator",它可能是用来模拟某种网络通信或者服务的。让我们深入探讨一下Mina...

    mina客户端服务器简易Demo

    无论是即时通讯应用、文件传输服务,还是其他基于网络的服务,Mina都能提供稳定高效的解决方案。 总的来说,Apache Mina是一个强大的工具,通过学习和实践这个"mina客户端服务器简易Demo",你可以快速掌握其基本...

    mina

    标题 "MINA" 指的是 Apache MINA (Multipurpose Infrastructure for Network Applications),这是一个由Apache软件基金会开发的Java框架,主要用于构建高性能、高可用性的网络应用程序。MINA提供了一个高级的网络...

Global site tag (gtag.js) - Google Analytics