huangfox

冰冻三尺,非一日之寒!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

未完待续》》》

目录:

一)同步、异步、阻塞、非阻塞

二)Java中的NIO

三)Mina 异步请求

四)Mina 同步请求

五)Mina 核心类及处理流程

六)Mina 线程模型

七)Mina 通用通讯框架(协议:ProtoBuf)

八)Mina 其他

 (注:部分内容整理来自网络资源!)


 

 

一)同步、异步、阻塞、非阻塞

1)同步阻塞

2)同步非阻塞

3)异步阻塞

4)异步非阻塞

阻塞与非阻塞是一个相对的问题——谁阻塞了谁?是两个“事物”的交互问题。

同步与异步通俗的来说是指——完成一件事的过程是“从头到尾”还是“多线操作”。

大多数认为阻塞就同步,非阻塞就异步。但是上文提到的“同步非阻塞”怎么理解呢?——同步非阻塞中的“非阻塞”是指不阻塞应用线程,如果kernel没有准备好会返回应用线程一个状态,但是应用线程会不停的“主动”检查这个状态,一直等到返回ok状态,因此说他还是个“同步”的操作。

link:

http://www.ibm.com/developerworks/cn/linux/l-async/ 

http://blog.csdn.net/historyasamirror/article/details/5778378

 

 

 二)Java中的NIO

 NIO主要关键点:

  • buffer
  • channel
  • selector

 

 

三)Mina 异步请求

 

 

 

四)Mina 同步请求

例如Mina的NioSocketConnector建立连接的过程如下(同步):

ConnectFuture connectF = connector.connect(new InetSocketAddress(ip,
				port));
connectF.awaitUninterruptibly();
session = connectF.getSession();

ConnectFuture调用awaitUninterruptibly方法后,将阻塞应用线程直到连接建立完成。此时将获得session对象。(如果不awaitUninterruptibly,从ConnectFuture中获取的session极有可能为null。)
因此这里的awaitUninterruptibly方法 将一个异步请求“活生生的”转变成一个同步请求。同理,write、read动作类似处理(同步):

write

WriteFuture writeF = session.write(msg);
writeF.awaitUninterruptibly();
if (writeF.getException() != null) {
    //异常处理  
} else if (writeF.isWritten()) {
    //准备读操作  
}

read

ReadFuture readF = session.read();
readF.awaitUninterruptibly();
if (readF.getException() != null) {
    //异常处理    
} else {
    //接收到消息,进行业务处理
}

具体参见实例:

http://www.cnblogs.com/huangfox/p/3461839.html

 

 

五)Mina 核心类及处理流程

 

 从上图可以关键的类包括:

IoService,IoFilterChain,IoHandler,IoSession

1)IoService

IoService负责底层IO操作,他的好处主要在于隐藏底层IO操作,方便使用;基于事件机制将同步IO转化成异步IO。

最常用的接口是SocketAcceptor、SocketConnector,用做TCP协议通讯下的服务端和客户端。

2)IoFilterChain

IoFilterChain主要负责数据包的处理工作,包括编码、解码等功能。其主要思想是——与业务逻辑代码分离。当然IofilterChain也是处理流程的扩展点,包括为处理流程添加线程池。

3)IoHandler

IoHandler主要实现业务逻辑(调用业务逻辑接口)。

4)IoSession

IoSession是对底层连接的封装,一个IoSession对应一个底层的IO连接。
发送数据其实是个异步的过程。发送的操作首先会逆向穿过IoFilterChain,到达IoService。但IoService上并不会直接调用底层IO接口来将数据发送出去,而是会将该次调用封装成一个WriteRequest,放入session的writeRequestQueue中,最后由IoProcessor线程统一调度flush出去。所以发送操作并不会引起上层调用线程的阻塞。

 

处理流程

1)建立连接

开启一个SocketAcceptor(服务端),会创建一个acceptor线程,他负责监听指定端口上的connect事件(维护一个selector)。获取新建的连接后封装成IoSession交由IoProcessor线程处理。
SocketConnector(客户端)类似会创建一个connector线程。

这类acceptor、connector线程可以生动的理解为“前台线程”,负责“接待工作”(connector),有客户来访将其登记(标示成一个业务需求-IoSession)交由具体的业务员(IoProcessor)处理。

2)processor处理

Processor线程主要负责具体的IO操作、filterChain、IoHandler执行。Processor线程的数量默认为cpu数量+1,主要是为了充分利用多核的处理能力。Processor线程的数量可以根据实际情况进行配置。
多个IoSession会被分配到多个Processor线程中,可以理解为一个Processor线程“服务”一个或多个IoSession对象。值得一提的是,N个IoProcessor形成一个处理池(SimpleIoProcessorPoll),分配Processor的时候根据IoSession的id绝对值模N进行分配。

具体代码如下:

private IoProcessor<S> getProcessor(S session) {
        IoProcessor<S> processor = (IoProcessor<S>) session.getAttribute(PROCESSOR);

        if (processor == null) {
            if (disposed || disposing) {
                throw new IllegalStateException("A disposed processor cannot be accessed.");
            }
       //取模分配
            processor = pool[Math.abs((int) session.getId()) % pool.length];

            if (processor == null) {
                throw new IllegalStateException("A disposed processor cannot be accessed.");
            }
        //session保定具体的processor线程
            session.setAttributeIfAbsent(PROCESSOR, processor);
        }

        return processor;
    }

在默认情况下filterChain、IoHandler的操作都是有IoProcessor顺序执行(执行完一个再执行下一个),如果IoHandler中的业务处理比较耗时,那么Processor线程将阻塞,后续的请求将得不到处理。即同时处理的请求数最多只有N个(N为Processor线程数量)。在高并发的情况下这种模式有待改进。(六 Mina线程模型 中将解答该问题)

接着上面的类比,前台(acceptor、connector)接待客户(session)分配给业务员(IoProcessor)进行服务, 业务员对客户进行交流(IO操作、编码、解码等)并执行相应的业务服务(IoHandler)。同理业务员每次只能服务一个客户,其他客户只能等待(假设其他业务员都有自己的客户)。

 

 

六)Mina 线程模型

接上文,上文提到“若IoHandler中的业务处理比较耗时,将阻塞当前Processor线程”,那么可以通过添加线程池处理这个问题。
Mina提供了一个很好的扩展点,可以在FilterChain添加线程池,让“下面”的业务处理过程并行起来。如图:

第一种模式:Mina默认的模式,IoProcessor全程服务。(One by one)

第二种模式:在FilterChain中加入ThreadPoolFilter,此时的处理流程变为Processor线程读取完数据后,执行IoFilterChain的逻辑。当执行到Thread Pool Filter的时候,该Filter会将后续的处理流程封装到一个Runnable对象中,并交由Filter自身的线程池来执行,而Processor线程则能立即返回来处理下一个IO请求。这样如果后面的IoFilter或IoHandler中有阻塞操作,只会引起Filter线程池里的线程阻塞,而不会阻塞住Processor线程,从而提高了服务器的处理能力。Mina提供了Thread Pool Filter的一个实现:ExecutorFilter。(本段内容为转载)

第三种模式:在合适的环节添加多个线程池,这种适合于FilterChain、IoHandler过程中存在多个计算密集型的任务。一般不需要使用,加大了代码复杂程度。

接着上面的类比,如果公司业务发展很好,客户增多,那么一个业务员(Processor)将很难及时服务到众多客户。于是公司决定业务员只负责与客户交流,具体的业务操作交由专门的业务服务团队(ThreadPool)。大家意会一下即可!

 

 

七)Mina 通用通讯框架(协议:ProtoBuf)

 

 

 

 

八)Mina 其他

 

 

 

 

posted on 2013-12-04 20:04  huangfox  阅读(7553)  评论(2编辑  收藏  举报