zoukankan      html  css  js  c++  java
  • Mina 专题

    未完待续》》》

    目录:

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

    二)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 其他

     

  • 相关阅读:
    Java架构师成长直通车百度云
    java架构师直通车百度云
    java架构师成长直通车
    初级Java程序员需要掌握哪些主流技术
    JAVA互联网架构师专题/分布式/高并发/微服务之咕泡学院学习笔记
    java架构师学习之路
    新手都能学懂的SpringBoot
    2020新版python最新就业班项目实战教程(完整)
    35个jQuery小技巧!
    web知识总结
  • 原文地址:https://www.cnblogs.com/huangfox/p/3458272.html
Copyright © 2011-2022 走看看