`
ikon
  • 浏览: 107159 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

MINA2.0 原理

阅读更多

客户端通信过程 
1.通过SocketConnector同服务器端建立连接 
2.链接建立之后I/O的读写交给了I/O Processor线程,I/O Processor是多线程的 
3.通过I/O Processor读取的数据经过IoFilterChain里所有配置的IoFilter,IoFilter进行消息的过滤,格式的转换,在这个层面可以制定一些自定义的协议 
4.最后IoFilter将数据交给Handler进行业务处理,完成了整个读取的过程 
5.写入过程也是类似,只是刚好倒过来,通过IoSession.write写出数据,然后Handler进行写入的业务处理,处理完成后交给IoFilterChain,进行消息过滤和协议的转换,最后通过I/O Processor将数据写出到socket通道 
IoFilterChain作为消息过滤链 
1.读取的时候是从低级协议到高级协议的过程,一般来说从byte字节逐渐转换成业务对象的过程 
2.写入的时候一般是从业务对象到字节byte的过程 
IoSession贯穿整个通信过程的始终 

整个过程可以用一个图来表现 


 
消息箭头都是有NioProcessor-N线程发起调用,默认情况下也在NioProcessor-N线程中执行 

类图 
http://mina.apache.org/class-diagrams.html#ClassDiagrams-ProtocolDecoderclassdiagram 

Connector 
作为连接客户端,SocketConector用来和服务器端建立连接,连接成功,创建IoProcessor Thread(不能超过指定的processorCount),Thread由指定的线程池进行管理,IoProcessor 利用NIO框架对IO进行处理,同时创建IoSession。连接的建立是通过Nio的SocketChannel进行。 

NioSocketConnector connector = new NioSocketConnector(processorCount); 
ConnectFuture future = connector.connect(new InetSocketAddress(HOSTNAME, PORT));建立一个I/O通道 

Acceptor 
作为服务器端的连接接受者,SocketAcceptor用来监听端口,同客户端建立连接,连接建立之后的I/O操作全部交给IoProcessor进行处理 
IoAcceptor acceptor = new NioSocketAcceptor(); 
acceptor.bind( new InetSocketAddress(PORT) ); 
Protocol 
利用IoFilter,对消息进行解码和编码,如以下代码通过 MyProtocolEncoder 将java对象转成byte串,通过MyProtocalDecoder 将byte串恢复成java对象 

Java代码
  1. connector.getFilterChain().addLast("codec",  new  ProtocolCodecFilter( new MyProtocalFactory()));  
  2. ......  
  3. public   class  MyProtocalFactory  implements  ProtocolCodecFactory {  
  4.  ProtocolEncoderAdapter encoder = new  MyProtocolEncoder();  
  5.  ProtocolDecoder decoder = new  MyProtocalDecoder() ;  
  6.  public  ProtocolDecoder getDecoder(IoSession session)  throws  Exception {  
  7.   return  decoder;  
  8.  }  
  9.  public  ProtocolEncoder getEncoder(IoSession session)  throws  Exception {  
  10.   return  encoder;  
  11.  }  
  12. }  
  13. ......  
  14. public   class  MyProtocalDecoder  extends  ProtocolDecoderAdapter  {  
  15.   
  16.  public   void  decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)  
  17.    throws  Exception {  
  18.     
  19.   int   id  = in.getInt();  
  20.   int   len = in.getInt();  
  21.   byte []  dst =  new   byte [len];  
  22.     
  23.   in.get(dst);  
  24.     
  25.   String name = new  String(dst,"GBK");  
  26.     
  27.   Item item = new  Item();  
  28.   item.setId(id);  
  29.   item.setName(name);  
  30.   out.write(item);  
  31.  }  
  32. }  
  33. ......  
  34. public   class  MyProtocolEncoder  extends  ProtocolEncoderAdapter {  
  35.   
  36.  public   void  encode(IoSession session, Object message,  
  37.    ProtocolEncoderOutput out) throws  Exception {  
  38.   Item item = (Item)message;  
  39.   int  byteLen =  8  + item.getName().getBytes("GBK").length ;  
  40.   IoBuffer buf = IoBuffer.allocate(byteLen);  
  41.   buf.putInt(item.getId());  
  42.   buf.putInt(item.getName().getBytes("GBK").length);  
  43.   buf.put(item.getName().getBytes("GBK"));  
  44.   buf.flip();  
  45.   out.write(buf);  
  46.     
  47.  }  
  48. }  


handler 
具体处理事件,事件包括:sessionCreated、sessionOpened、sessionClosed、sessionIdle、exceptionCaught、messageReceived、messageSent。 
connector.setHandler(new MyHandler());MyHandler继承IoHandlerAdapter类或者实现IoHandler接口.事件最终由IoProcessor线程发动调用。 
Processor 
I/O处理器、允许多线程读写,开发过程中只需要指定线程数量,Processor通过Nio框架进行I/O的续写操作,Processor包含了Nio的Selector的引用。这点也正是mina的优势,如果直接用Nio编写,则需要自己编写代码来实现类似Processor的功能。正因为 I/O Processor是异步处理读写的,所以我们有时候需要识别同一个任务的消息,比如一个任务包括发送消息,接收消息,反馈消息,那么我们需要在制定消息格式的时候,消息头里能包含一个能识别是同一个任务的id。 
I/O Porcessor线程数的设置 :如果是SocketConnector,则可以在构造方法中指定,如:new SocketConnector(processorCount, Executors.newCachedThreadPool());如果是SocketAcceptor,也是一样的:SocketAcceptor acceptor = new SocketAcceptor(ProcessorCount, Executors.newCachedThreadPool()); 
processorCount为最大Porcessor线程数,这个值可以通过性能测试进行调优,默认值是cpu核数量+1(Runtime.getRuntime().availableProcessors() + 1)。 
比较奇怪的是,每个IoProcessor在创建的时候会本地自己和自己建立一个连接? 

IoSession 
IoSession是用来保持IoService的上下文,一个IoService在建立Connect之后建立一个IoSession(一个连接一个session),IoSession的生命周期从Connection建立到断开为止 
IoSession做两件事情: 
1.通过IoSession可以获取IoService的所有相关配置对象(持有对IoService,Processor池,SocketChannel,SessionConfig和IoService.IoHandler的引用) 
2.通过IoSession.write 是数据写出的入口 

关于线程 
http://mina.apache.org/configuring-thread-model.html 
ThreadModel 1.x版本的mina还有线程模式选项在2.x之后就没有了 
1.x版本指定线程模式 
SocketConnectorConfig cfg = new SocketConnectorConfig(); 
cfg.setThreadModel(ThreadModel.MANUAL); 

MINA有3种worker线程 
Acceptor、Connector、I/O processor 线程 
Acceptor Thread 
一般作为服务器端链接的接收线程,实现了接口IoService,线程的数量就是创建SocketAcceptor 的数量 
Connector Thread 
一般作为客户端的请求建立链接线程,实现了接口IoService,维持了一个和服务器端Acceptor的一个链接,线程数量就是创建SocketConnector 的数量 

Mina的SocketAcceptor和SocketConnector均是继承了BaseIoService,是对IoService的两种不同的实现 
I/O processor Thread 
作为I/O真正处理的线程,存在于服务器端和客户端,用来处理I/O的读写操作,线程的数量是可以配置的,默认最大数量是CPU个数+1 
服务器端:在创建SocketAcceptor的时候指定ProcessorCount 
SocketAcceptor acceptor = new SocketAcceptor(Runtime.getRuntime().availableProcessors() + 1, Executors.newCachedThreadPool()); 
客户端:在创建SocketConnector 的时候指定ProcessorCount 
SocketConnector connector = new SocketConnector(Runtime.getRuntime().availableProcessors() + 1, Executors.newCachedThreadPool()); 
I/O Processor Thread,是依附于IoService,类似上面的例子SocketConnector connector = new SocketConnector(Runtime.getRuntime().availableProcessors() + 1, Executors.newCachedThreadPool());是指SocketConnector这个线程允许CPU+1个I/O Processor Thread 
NioProcessor虽然是多线程,但是对与一个连接的时候业务处理只会使用一个线程进行处理(Processor线程对于一个客户端连接只使用一个线程NioProcessor-n)如果handler的业务比较耗时,会导致NioProcessor线程堵塞 ,在2个客户端同时连接上来的时候会创建第2个(前提是第1个NioProcessor正在忙),创建的最大数量由Acceptor构造方法的时候指定。如果:一个客户端连接同服务器端有很多通信,并且I/O的开销不大,但是Handler处理的业务时间比较长,那么需要采用独立的线程模式,在 FilterChain的最后增加一个ExecutorFitler : 
acceptor.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool())); 
这样可以保证processor和handler的线程是分开的,否则:客户端发送3个消息,而服务器对于每个消息要处理10s左右,那么这3个消息是被串行处理,在处理第一个消息的时候,后面的消息将被堵塞,同样反过来客户端也有同样的问题。 

客户端Porcessor堵塞测试情况: 
1.以下代码在建立连接后连续发送了5个消息(item)

 
Java代码
  1. ConnectFuture future = connector.connect( new  InetSocketAddress(HOSTNAME, PORT));  
  2.                 future.awaitUninterruptibly();  
  3.                 session = future.getSession();  
  4.                 Item item = new  Item();  
  5.                 item.setId(12345 );  
  6.                 item.setName("hi");  
  7.                 session.write(item);  
  8.                 session.write(item);  
  9.                 session.write(item);  
  10.                 session.write(item);  
  11.                 session.write(item);  




2.在handle的messageSent方法进行了延时处理,延时3秒 

 
Java代码
  1. public   void  messageSent(IoSession session, Object message)  throws  Exception {  
  2.       Thread.sleep(3000 );  
  3.       System.out.println(message);  
  4.         
  5.   }  



3.测试结果 
5个消息是串行发送,都由同一个IoPorcessor线程处理

             
Java代码
  1. session.write(item);  
  2.               session.write(item);  
  3.               session.write(item);  
  4.               session.write(item);  
  5.               session.write(item);  


服务器端每隔3秒收到一个消息。因为调用是由IoProcessor触发,而一个connector只会使用一个IoProcessor线程 

4.增加ExecutorFilter,ExecutorFilter保证在处理handler的时候是独立线程 
connector.getFilterChain().addLast("threadPool", new ExecutorFilter(Executors.newCachedThreadPool())); 
5.测试结果 
4个session.wirte变成了并行处理,服务器端同时收到了5条消息

 

 

 

 

  • 大小: 26 KB
分享到:
评论

相关推荐

    mina2.0案例

    **标题:“mina2.0案例”** **描述:**该案例是关于Java网络编程中使用的异步传输框架——Mina 2.0的实践应用,包括了服务端(server)和客户端(client)的实现。 **知识点详解:** 1. **Mina 2.0框架**:Mina...

    Mina2.0框架源码剖析

    本文将对Mina2.0框架进行源码层面的剖析,以便深入理解其工作原理。 首先,让我们从`MinaTimeServer.java`这个示例代码开始。在这个例子中,我们看到一个简单的TCP服务器,它监听在特定端口上的连接,并处理来自...

    Mina 2.0快速入门与源码解析

    接下来,我们将逐步深入分析 Mina 2.0 的核心组件及其实现原理。 **2.1 IoAcceptor** `IoAcceptor` 接口是 Mina 2.0 中的核心接口之一,它代表了一个网络服务端点。通过该接口可以设置各种处理器、配置参数以及...

    MIna2.0学习笔记

    Mina2.0作为其更新版本,提供了更丰富的功能和优化的性能,使得开发者能更高效地构建网络服务。 **入门** 1. **下载使用的Jar包**:在开始Mina2.0的学习之前,你需要从Apache官网或其他可靠的源下载Mina的最新版本...

    Mina2.0学习笔记(修订版)

    ### Mina2.0学习笔记核心知识点概览 #### 一、Mina入门与环境搭建 **Mina简介** Mina是Apache旗下的一款强大的网络应用框架,专为高性能和高可扩展性网络应用设计,其核心是利用Java NIO技术提供事件驱动的异步API...

    Mina2.0完全剖析,完全自学手册

    ### Mina2.0完全剖析,完全自学手册 #### Apache Mina 概述 Apache Mina(Multipurpose Infrastructure Networked Applications)是一个强大的网络应用框架,主要用于帮助开发者构建高性能且易于扩展的网络应用程序...

    Mina2.0 example HttpServer

    通过阅读和分析Mina2.0的源码,我们可以更深入地理解其内部工作机制,从而更好地利用这一工具。对于开发人员来说,理解并掌握HttpServer的实现原理,不仅有助于提高代码质量,还能提升解决网络通信问题的能力。因此...

    Mina2.0工作原理以及配置注意事项

    ### Mina2.0工作原理及配置注意事项 #### 一、Mina简介 **Apache Mina** 是一款高性能且易于使用的网络应用程序框架,其主要目的是帮助开发者轻松构建高性能和高可靠性的网络应用。该框架的核心优势在于其采用了...

    mina2.0用户指南

    总的来说,mina2.0用户指南主要涵盖了NIO的基础概念、MINA框架的核心组件、以及NIO与传统BIO在原理和实际应用上的差异。掌握这些知识点对于开发高性能网络应用至关重要。开发者在深入学习本用户指南后,应能够熟练地...

    Mina2.0框架源码剖析.pdf

    《Mina2.0框架源码剖析》 Apache Mina是一个高性能、易用的网络通信框架,常用于构建网络服务应用,如TCP/IP和UDP协议的服务器。在Mina2.0中,它提供了丰富的API和过滤器系统,使得开发者能够更方便地处理网络通信...

    mina2.0下一个例子

    《MINA 2.0深度探索:从一个实例入手...通过实践一个MINA实例,我们可以深入了解其工作原理,并掌握如何构建高性能的网络服务。对于想要深入研究网络编程和I/O模型的开发者来说,MINA无疑是一个值得学习和探索的工具。

    Mina 2.0 中文参考手册

    - **Java IO/NIO**:理解Java标准输入输出流和非阻塞I/O的基本原理,这是Mina框架的基础。 - **Socket编程**:熟悉Socket通信机制,包括客户端与服务器端的交互过程。 - **多线程与并发**:精通Java线程模型和并发...

    Apache Mina Server 2.0 抢鲜体验

    7. **源码分析**:由于标签中提到了“源码”,因此,对于有志于深入理解Mina工作原理的开发者来说,阅读和分析Apache Mina的源码可以帮助他们更好地优化自己的网络应用程序,提高性能和稳定性。 8. **性能优化**:...

    Mina2.0框架源码剖析(六).pdf

    《Mina2.0框架源码剖析(六)》这篇文档主要关注的是Mina框架中的ExpiringMap、IoSession及其相关概念,这些内容对于理解Mina框架如何处理数据过期、会话管理和读写操作至关重要。 ExpiringMap是一个实现自动过期功能...

    mina 2.0压缩包

    这些示例可以帮助开发者快速理解并掌握Mina的工作原理和使用方法,例如: 1. **Echo示例**:这是一个简单的回显服务器,展示了如何接收和发送数据的基本流程。 2. **Chat示例**:实现了一个多用户聊天室,演示了...

Global site tag (gtag.js) - Google Analytics