MINA 网络库的剖析

MINA  网络库的剖析

一、MINA  概述    

      Mina是Apache社区维护的一个开源的高性能IO框架的底层还是利用了jdk提供了nio功能,mina只是对nio进行封装,包括MINA用的线程池都是jdk直接提供的。

1.1 MINA 的工作流程

    Mina的主端由accept、prossser,session 组成其中accept主要负责事件的监听,若有新连接则建立一个新的session;cessor则负责处理session对应的发送数据和接收数据并调用上层处理;session则缓存当前连接数据

 

具体过程:

 

1.Accept

    Mina采用懒启动的模式,即最少启动线程,MINA server启动的时候,只有一个线程-accept,并且accept线程只有一个,在指定的端口进行监听(可以同时监听多个端口,mina可以绑定多端口)

 MINA 网络库的剖析_第1张图片

 

  在服务器端,bind一个端口后,会创建一个Acceptor线程来负责监听工作。这个线程的工作只有一个,调用Java NIO接口在该端口上select connect事件,获取新建的连接后,封装成IoSession,交由后面的Processor线程处理。在客户端,也有一个类似的,叫Connector的线程与之相对应。这两类线程的数量只有1个,外界无法控制这两类线程的数量。

 

2.Processor

 

  Processor线程主要负责具体的IO读写操作和执行后面的IoFilterChainIoHandler逻辑。Processor线程的数量N默认是CPU数量+1,可以通过配置参数来控制其数量。前面进来的IoSession会被分配到这NProcessor线程中。

  每个Porcessor线程中都维护着一个selector,对它维护的IoSession集合进行select,然后对select的结果进行遍历,逐一处理。像前面提到的,读取数据,以事件的形式通知后面IoFilterChain;以及对写请求队列的flush操作,都是在这类线程中来做的。

  通过将session均分到多个Processor线程里进行处理,可以充分利用多核的处理能力,减轻select操作的压力。默认的Processor的线程数量设置可以满足大部分情况下的需求,但进一步的优化则需要根据实际环境进行测试。MINA 网络库的剖析_第2张图片

Processor具体操作:

(1)把新添加进来的session注册到当前processorSelector里面的  read事件,并初始化session
2判断当前Selector是否有读写事件;
3、若第2步有读事件时,进入步骤4,若没有的话,直接到第6步;
4处理当前读事件,并把处理后的数据放入到flush队列里面;
5把第4步执行的结果flush到客户端;
6处理session,比如session idle时间等。
7重新执行第1步,循环执行。

为什么采取多线程:

  如果只有单线程的话,只有当前面的IO请求处理完毕后,才会取下一个IO请求进行处理。也就是说,如果IoFilterIoHandler中有比较耗时的操作的话(如:读取数据库等),Processor线程将会被阻塞住,这样的话对工作效率的影响就太大了。

线程池应该添加的位置:

  IoFilterChain中加入了Thread Pool Filter。这样的操作是的Processor不会阻塞提高了工作效率。开发者也可以在chain中加入多个ExecutorFilter但很少有人这样操作。

3.Session

  session做为一个连接的具体对象,缓存当前连接用户的一些信息,session对象是绑定在SelectableChannel的一个attach

二、MINA 网络库如何使用

1.使用MINA步骤:

(1):创建一个NioSocketAcceptor对象;

(2):为NioSocketAcceptor对象添加Filter对象,这个Filter可以认为是二进制数据与对象之间的转换器,可以设置多个,可以使用框架自带的,我们也可以自己写,在这里我们使用框架自带的;

(3):创建一个继承自IoHandlerAdapter的业务逻辑处理类MinaServerHandler,并且重写IoHandlerAdapter里面的方法,我们这个示例中将仅仅是打印一些输出信息;

(4):将MinaServerHandler对象设置到NioSocketAcceptor对象上面;

(5):为当前NioSocketAcceptor绑定IP以及端口号;

2.常用接口的使用

1.IoService

    用于提供连接,他是服务器端的IoAcceptor;提供IO 服务和管理IoSession的功能。相当于是Mina的Socket层,负责所有SocketIO事件的注册,select,分发等。它位于org.apache.mina.core.service包内,它有两个子接口,表示Server端接收方的IoAcceptor和Client发起方的IoConnector,以及所有的实现类 

 

2.IoAcceptor:
这个接口是TCPServer 的接口,主要增加了void bind()监听端口、void unbind()解除对套接字的监听等方法。这里与传统的Java 中的ServerSocket 不同的是IoAcceptor 可以多次调用bind()方法(或者在一个方法中传入多个SocketAddress 参数)同时监听多个端口

 

3.IoConnector:
    这个接口是TCPClient 的接口,主要增加了ConnectFuture connect(SocketAddressremoteAddress,SocketAddress localAddress)方法,用于与Server 端建立连接,第二个参数如果不传递则使用本地的一个随机端口访问Server 端。这个方法是异步执行的,同样的,也可以同时连接多个服务端

 

4.IoSession:

    在每一次连接建立成功之后都会创建一个IoSession对象出来,并且在创建该对象的时候创建一个IoFilter对象出来,通过IoSession的session id来为当前IoSession设置处理他的IoProcessor;

 

5.IoProcessor:

    用于检查是否有数据在通道上面进行读写,在我们创建Acceptor或者Connector的时候,默认会创建一个线程池,里面存储的就是IoProcessor线程,该线程里面是拥有自己的Selector的,这个是MINA为我们做的一点优化,我们通常使用NIO的话是只有一个Selector的,而MINA中的

 

6.IoFilter:

    用于定义拦截器,这些拦截器可以包括日志输出、数据编解码等等,只要用于二进制数据和对象之间的转换;

IoBuffer:消息缓存区;

 

8.IoHandler:

处于IoFilter的尾部,用于真正的业务逻辑处理,所以我们在使用MINA的时候是必须要提供IoHandler对象的,因为是靠他来进行真正业务处理的;这个接口是你编写业务逻辑的地方,读取数据、发送数据基本都在这个接口总完成

 

9.IoBuffer:

    缓冲区这是一个ByteBuffer的替代类,这主要是因为ByteBuffer 只提供了对基本数据类型的读写操作,没有提供对字符串等对象类型的读写方法,使用起来更为方便,另外,ByteBuffer 是定长的,如果想要可变,将很麻烦,

 

10.IoFuture:

Mina 的很多操作中,你会看到返回值是XXXFuture,实际上他们都是IoFuture 的子类,看到这样的返回值,这个方法就说明是异步执行的,主要的子类有ConnectFuture、CloseFuture 、ReadFuture 、WriteFuture 。

 

三、MINA网络库的细节处理

1、粘包与段包

粘包:指TCP协议中,发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。造成的可能原因:发送端需要等缓冲区满才发送出去,造成粘包 接收方不及时接收缓冲区的包,造成多个包接收

断包:也就是数据不全,比如包太大,就把包分解成多个小包,多次发送,导致每次接收数据都不全。

2、消息传输的格式

消息长度+消息头+消息体即前N个字节用于存储消息的长度,用于判断当前消息什么时候结束。

3、编码与解码

    MINA中对象的编码与解码用的都是JDK提供的ObjectOutputStream来实现的

编码:即把我们的消息编码成二进制形式,能以字节的形式在网络中传输。

解码:即把我们收到的字节解码成我们代码中的对象。
 

4、MINA中消息的处理实现

     消息的接受处理,我们常用的是TCP协议,而TCP协议会分片的,在下面的代码中,具体功能就是循环从通道里面读取数据,直到没有数据可读,或者buffer满了,然后就把接受到的数据发给解码工厂进行处理。

 

 

 

你可能感兴趣的:(MINA,网络库剖析)