`
maozilee
  • 浏览: 247243 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

[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 的学习热情吧!感兴趣的童鞋不妨把它当成一个课后作业来做做吧 !!  ^_^

 

分享到:
评论
1 楼 yuer2084 2012-08-09  
IoBuffer的capacity 修改是可能的
IoBuffer可以autoExpand。这样超过的数据put如缓冲时会自动扩充capacity(整数倍)。
也可以手动调用capacity(int)方法,修改。

相关推荐

    mina core 包

    org.apache.mina.core.buffer.IoBuffer mina core 包

    Mina框架+常用JAR包

    Mina框架+常用JAR包 Mina框架+常用JAR包 Mina框架+常用JAR包 Mina框架+常用JAR包 Mina框架+常用JAR包 Mina框架+常用JAR包

    mina 框架学习文档

    apache mina 框架的学习文档,通过此文档可以基本了解mina框架。

    Mina框架入门介绍

    pache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP、UDP/IP协议栈的通信框架(然,也可以提供JAVA 对象的序列化服务、虚拟机管道通信服务等),Mina 可以帮助我们快速开发高性能、高扩展性...

    java mina框架全套

    java mina框架

    apache mina 框架实例

    apache mina 框架 实例 自定义协议包 自定义编码器 解码器 服务端 客户端

    Apache mina框架入门教程

    该文档较好的介绍了,apache mina框架的使用方法。

    mina框架资源包

    要实现mina框架最基本的资源包,拥有这个就可以实现mina的通讯

    mina框架的demo 入门,开发

    mina框架的demo 入门,开发 学习

    Android Mina框架使用

    Android端集成Mina框架实现长连接,完美解决断线重连问题,修复断线重连打开多端口问题。

    Java springboot 整合mina 框架,nio通讯基础教程,mina框架基础教程.zip

    Java_NIO基础教程、MINA教程, 并附上基于springboot 整合mina的基础平台框架,可以直接使用,也可以借鉴下

    mina框架源码及jar包

    apache-mina-2.0.4 mina框架的源码及jar包

    java-mina通信框架详解.docx

    详细介绍mina框架的各个组成部分、服务器端的开发、客户端开发。并根据本人在工程项目中使用的代码,详细讲解了服务器端是客户端实现。实现了json格式的通信、以及文件的上传于下载等功能。图文并茂,以开发者的角度...

    Mina框架简介

    Mina 可以帮助我们快速开发高性能、高扩展性的网络通信应用,Mina 提供了事件驱动、异步(Mina 的异步IO 默认使用的是JAVA NIO 作为底层支持)操作的编程模型。主要接收2.x版本

    mina框架使用总结

    nio的经典框架mina 在此基础上发展的netty是nio经典之中的经典

    mina框架demo

    使用MINA框架来开发的网络应用程序代码结构更清晰;MINA框架完成了底层的线程管理;MINA内置的编码器可以满足大多数用户的需求,省去了开发人员消息编码解码的工作。

    基于Java的mina框架

    基于Java的米娜框架,报告对使用基于Java、websocket协议的网页聊天室的过程和技术做了详细的叙述首先,对现有网页进行了分析与评价。首先, 启动后台服务器,然后连接站点,客户端在pc端输入网站或者在手机端扫...

    Mina通信框架应用示例

    Mina通信框架应用示例,学会运用Mina 框架

    MINA长连接框架实现通讯

    mina 通讯 实现server端与基于Android系统的client端通讯

    MiNA框架新人指导

    在资金线混有两个技术框架是一定要懂得如何使用的,它们就是MINA和HTTPCLIENT(迓没听过的,就先百度一下) 。支付宝和银行前置机乊间的通讯基本都是使用者两种框架,即使你丌懂SOCKET戒者HTTP很底层的协议也没多大...

Global site tag (gtag.js) - Google Analytics