搜索
您的当前位置:首页正文

高性能JAVA网络框架 MINA

来源:爱go旅游网
ApacheMINA(MultipurposeInfrastructureforNetworkApplications)是Apache组织一个较新的项目,它为开发高性能和高可用性的网络应用程序提供了非常便利的框架。当前发行的MINA版本支持基于JavaNIO技术的TCP/UDP应用程序开发、串口通讯程序(只在最新的预览版中提供),MINA所支持的功能也在进一步的扩展中。简介ApacheMINA是一个网络应用程序框架,用来帮助用户简单地开发高性能和高可靠性的网络应用程序。它提供了一个通过JavaNIO在不同的传输例如TCP/IP和UDP/IP上抽象的事件驱动的异步API。MINA虽然简单但是仍然提供了全功能的网络应用程序框架:●为不同的传输类型提供了统一的API:○通过JavaNIO提供TCP/IP和UDP/IP支持○通过RXTX提供串口通讯(RS232)○In-VM管道通讯○你能实现你自己的API!●过滤器作为一个扩展特性;类似Servlet过滤器●低级和高级的API:○低级:使用字节缓存(ByteBuffers)○高级:使用用户定义的消息对象(objects)和编码(codecs)●高度定制化线程模型:○单线程○一个线程池○一个以上的线程池(也就是SEDA)●使用Java5SSL引擎提供沙盒(Out-of-the-box)SSL·TLS·StartTLS支持●超载保护和传输流量控制●利用模拟对象进行单元测试●JMX管理能力●通过StreamIoHandler提供基于流的I/O支持●和知名的容器(例如PicoContainer、Spring)集成●从Netty平滑的迁移到MINA,Netty是MINA的前辈。MINA版本Mina的API当前主要有三个分支,分别是:2.0.x目前处于SVNtrunk上的版本,Mina社区对该版本的API进行了全新的设计1.1.x为当前用于产品开发的版本,适用于5.0以上的JDK,最新版本为1.1.51.0.x是1.1.x的JDK1.4的兼容版本,最新版本为1.0.8这里将要介绍的是2.0.x版。虽然当前的稳定版本还是1.1.x,但是按照Mina团队之前的开发计划,2.0.x即将在08年夏季正式发布,并且在2.0.x中对Spring等IoC的集成进行了简化,添加了基于OGNL的JMX远程管理支持,使用基于JavaAnnotation的全新API大大简化了状态机编程,新的基于ApacheAPR的基础I/O组件促进了进一步的效率提升(据官方评测,APR的效率较之SunNIO要高出约10%)。由于这一系列的重大改进,使得2.0.x成为十分令人期待的一个版本,无论是Mina新手还是老用户,如果你对这个项目抱有兴趣,便很有必要提前对这个版本进行一些了解。首先让我们对异步I/O做一些基本的了解。异步I/O模型大体上可以分为两种,反应式(Reactive)模型和前摄式(Proactive)模型:传统的select/epoll/kqueue模型,以及JavaNIO模型,都是典型的反应式模型,即应用代码对I/O描述符进行注册,然后等待I/O事件。当某个或某些I/O描述符所对应的I/O设备上产生I/O事件(可读、可写、异常等)时,系统将发出通知,于是应用便有机会进行I/O操作并避免阻塞。由于在反应式模型中应用代码需要根据相应的事件类型采取不同的动作,最常见的结构便是嵌套的if{...}else{...}或switch,并常常需要结合状态机来完成复杂的逻辑。前摄式模型则恰恰相反。在前摄式模型中,应用代码主动地投递异步操作而不管I/O设备当前是否可读或可写。投递的异步I/O操作被系统接管,应用代码也并不阻塞在该操作上,而是指定一个回调函数并继续自己的应用逻辑。当该异步操作完成时,系统将发起通知并调用应用代码指定的回调函数。在前摄式模型中,程序逻辑由各个回调函数串联起来:异步操作A的回调发起异步操作B,B的回调再发起异步操作C,以此往复。Reactor和Proactor同为事件驱动I/O模型,其本质区别在于事件触发时机:Reactor在I/O设备就绪,即可以立即执行I/O调用而无需阻塞时触发,只有这时才可以放心大胆的执行I/O调用;而Proactor则允许在任意时刻发起I/O调用请求,并在I/O调用完成时触发事件。Proactor可以直接利用系统提供的aio、IOCP等异步I/O机制实现。不过鉴于一时之间各种平台上aio接口实现的兼容性、功能、性能等方面的表现都还比较不靠谱,常见平台里还是Win32IOCP对Proactor的原生支持最好。当系统不提供原生的异步I/O机制时,也可以使用Reactor模拟实现。相关内容可参见这篇文章。MINA正是借由JavaNIO的Reactor实现的模拟Proactor模型。Boost.Asio的Proactor内核在非NTWin32平台上也是利用select()/kqueue()/epoll等Reactor模拟实现的。Reactor按照事件触发方式又可分为level-triggered(LT)和edge-triggered(ET)两种,其区别详见epoll的manpage。传统的select()/poll()都属于LTReactor;kqueue()则是ETReactor;epoll是个两面派,LT/ET语义通吃。前摄式模型相较于反射式模型往往更加难以编程。然而在具有原生异步I/O支持的操作系统中(例如支持IOCompletionPort的Win32系统),采用前摄式模型往往可以取得比反应式模型更佳的效率。在没有原生异步I/O支持的系统中,也可以使用传统的反应式API对前摄式模型予以模拟。在现代的软硬件系统中,使用epoll和kqueue的前摄式模型实现同样可以轻松解决C10K问题。前摄式模型的一个显著优势是在实现复杂逻辑的时候不需要借助于状态机。因为状态机已经隐含在由回调串联起来的异步操作链当中了。如果上述内容难以理解,可以参考Boost.Asio,这是一个相当优秀的跨平台C++前摄式I/O模型实现。MINA框架的常用类类NioSocketAcceptor用于创建服务端监听;类NioSocketConnector用于创建客户端连接;类IoSession用来保存会话属性和发送消息;类IoHandlerAdapter用于定义业务逻辑,常用的方法有:方法定义sessionCreated()当会话创建时被触发sessionOpened()当会话开始时被触发sessionClosed()当会话关闭时被触发sessionIdle()当会话空闲时被触发exceptionCaught()当接口中其他方法抛出异常未被捕获时触发此方法messageRecieved()当接收到消息后被触发messageSent()当发送消息后被触发应用示例所需jar包slf4j-api.jar、slf4j-jdk14.jar、MINA-core-2.0.0-M1.jar。相关包可到官方网站下载。首先定义一个业务逻辑处理器TimeServerHandler,继承自IoHandlerAdapter,实现的功能有:当客户端创建会话时会显示客户端设备的IP和端口;当客户端输入quit时结束会话;客户端输入其它内容时则向客户端发送当前时间。代码如下:[java]viewplaincopyprint?

1.publicclassTimeServerHandlerextendsIoHandlerAdapter{2.3.@Override4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.}publicvoidsessionCreated(IoSessionsession){//显示客户端的ip和端口System.out.println(session.getRemoteAddress().toString());}@OverridepublicvoidmessageReceived(IoSessionsession,Objectmessage)throwsException{Stringstr=message.toString();if(str.trim().equalsIgnoreCase(\"quit\")){session.close();//结束会话return;}Datedate=newDate();session.write(date.toString());//返回当前时间的字符串System.out.println(\"Messagewritten...\"+str);}定义一个类MinaTimeServer用来启动服务端:[java]viewplaincopyprint?

1.publicclassMinaTimeServer{2.3.4.5.6.7.8.9.10.11.12.13.端口号14.15.16.17.}acceptor.bind();//启动监听publicstaticvoidmain(String[]args)throwsIOException{acceptor=newNioSocketAcceptor();acceptor.getFilterChain().addLast(\"logger\",newLoggingFilter());//acceptor.getFilterChain().addLast(\"codec\ProtocolCodecFilter(newTextLineCodecFactory(Charset.forName(\"UTF-8\"))));//指定编码过滤器acceptor.getFilterChain().addLast(\"codec\",newProtocolCodecFilter(newTextLineCodecFactory()));//支持中文acceptor.setHandler(newTimeServerHandler());//指定业务逻辑处理器acceptor.setDefaultLocalAddress(newInetSocketAddress(PORT));//设置privatestaticIoAcceptoracceptor;privatestaticfinalintPORT=9123;//定义监听端口客户端:定义类TimeClientHandler来处理消息接收事件[java]viewplaincopyprint?

1.publicclassTimeClientHandlerextendsIoHandlerAdapter{2.3.4.5.6.7.8.9.10.11.}publicTimeClientHandler(){}@OverridepublicvoidmessageReceived(IoSessionsession,Objectmessage)throwsException{System.out.println(message);//显示接收到的消息}定义MinaTimeClient类用于连接服务端,并向服务端发送消息:[java]viewplaincopyprint?

1.publicclassMinaTimeClient{2.3.4.5.6.器7.8.9.10.11.12.13.14.开15.connector.dispose();connector.getFilterChain().addLast(\"codec\",newProtocolCodecFilter(newTextLineCodecFactory()));connector.setConnectTimeout(30);connector.setHandler(newTimeClientHandler());//设置事件处理器ConnectFuturecf=connector.connect(newInetSocketAddress(\"127.0.0.1\",9123));//建立连接cf.awaitUninterruptibly();//等待连接创建完成cf.getSession().write(\"hello\");//发送消息cf.getSession().write(\"quit\");//发送消息cf.getSession().getCloseFuture().awaitUninterruptibly();//等待连接断publicstaticvoidmain(String[]args){//创建客户端连接器.NioSocketConnectorconnector=newNioSocketConnector();connector.getFilterChain().addLast(\"logger\",newLoggingFilter());//connector.getFilterChain().addLast(\"codec\newProtocolCodecFilter(newTextLineCodecFactory(Charset.forName(\"UTF-8\"))));//设置编码过滤16.17.18.}}运行服务端server,再启动客户端MinaTimeClient,可看到进行通讯信息交互。另在MinaTimeServer类中增加下面方法进行客户端连接总数以及服务端主动向客户端发送信息等测试。[java]viewplaincopyprint?

1.publicstaticvoidstartMinaServer(){2.3.4.5.6.7.8.端口号9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.returnnum;intnum=acceptor.getManagedSessionCount();System.out.println(\"num:\"+num);/***获得客户端连接总数*@return*/publicstaticintgetConNum(){}try{acceptor.bind();}catch(IOExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}//启动监听acceptor=newNioSocketAcceptor();acceptor.getFilterChain().addLast(\"logger\",newLoggingFilter());//acceptor.getFilterChain().addLast(\"codec\ProtocolCodecFilter(newTextLineCodecFactory(Charset.forName(\"UTF-8\"))));//指定编码过滤器acceptor.getFilterChain().addLast(\"codec\",newProtocolCodecFilter(newTextLineCodecFactory()));//支持中文acceptor.setHandler(newTimeServerHandler());//指定业务逻辑处理器acceptor.setDefaultLocalAddress(newInetSocketAddress(PORT));//设置27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.}/***向每个客户端发送消息*@return*/publicstaticvoidsendConMessage(){IoSessionsession;MapconMap=acceptor.getManagedSessions();Iteratoriter=conMap.keySet().iterator();while(iter.hasNext()){Objectkey=iter.next();session=(IoSession)conMap.get(key);session.write(\"\"+key.toString());}}

因篇幅问题不能全部显示,请点此查看更多更全内容

Top