java io模型浅谈

Posted 小技一碟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java io模型浅谈相关的知识,希望对你有一定的参考价值。

        作为一个应用程序,除了单机版演示程序外,基本上都需要与外部进行通讯。如文件读写,mysql,redis,mq等第三方数据存储通讯。而应用系统内组件间的通信就需要自定义协议进行数据交换,常见的应用层如http、socket都涉及到io模型机制。



        网上大把的讲解boi和nio原理的文章,下面主要根据Doug Lea 大神在State University of New York at Oswego 教程结合自己的个人理解进行java io的设计思路的分析,有疑问的地方大家可以拿出来讨论。

       对于一个后台服务程或者中间库组件,大部分有如下的基础处理逻辑:

    1. Read Request         读取请求内容

    2. Decode Request      解码请求内容

    3. Process Service       业务逻辑处理

    4. Encode Response    编码应答消息

    5. Send Response        发送请求应答

        因业务逻辑不同,应用程序在上面每个步骤所进行的处理不同,比如读取请求内容,就有json、xml、二进制等内容格式。 Decode Request就是根据具体的协议进行解码。

        基于上面的处理步骤,常见的io模型有如下几种:


BIO(典型IO模型)

       

    java io模型浅谈

     每个request开启一个线程,处理上面所有的步骤。下面简单伪代码说明

       

     server接受client请求

java io模型浅谈

      每个请求启动一个线程进行处理(这里可以使用线程池)

     

java io模型浅谈

     优点:编码简单,业务逻辑清晰。 适用于业务量不大情景; 

      缺点:每个client request一个线程进行处理,业务量持续增长,过多线程会增加程序内存,且频繁线程切换,会增加业务处理时间。即使采用线程池,线程池无空闲线程时,多余请求就会处理等待状态,无法及时应答客户端。同时,无法做到平滑扩容。


NIO(异步IO模型)

        异步io的思想就是分而治之,我们可以这样来理解,上面的所有步骤(read request、decode request 、handler server、encode response 、send response)分成不同的非阻塞事件(可以类似button click event),并给上面的所有事件添加handler回调处理(类似 click listener)。当事件被触发时候(button be clicked),执行响应的handler事件。


button 异步事件驱动


java io模型浅谈

    当然 异步io只是类似上面的思想,具体的实现和设计有一定区别,大家可以通过熟悉的button事件来进行理解。

    优点:

    1. 更少的资源,不需要每个client一个线程进行处理;

    2. 不需要频繁的线程间调度,更少的锁操作

    缺点:

    1. 编程难度增加,一个完整的逻辑被切分成不同事件进行处理

    2. 所有的事件分发通过一个线程进行,有一定成都的延时

            


NIO(reactor 单线程模型)

         单线程reactor模型,直接上图类比

java io模型浅谈

       参照上图的button 点击事件类比:

  1.  Ractor模块负责将io事件分发到对应的handler,类似button 中awt thread;

  2. acceptor、read、send 负责io事件的处理,类似awt ActionListeners;

  3. io事件的绑定和handler绑定,类似act addActionListeners;

  4. IO事件在这里包括socket的连接和断开,数据的读写。其中acceptor负责处理socket连接事件,read 负责数据读,send负责数据写;

  5. 这里的实现需要java nio的支持,包括 channles、buffers、Selectors、SelectionKeys;


下面就按照上面的总体思想,用java nio 来实现reactor模型。

       reactor  io事件分发模块

       

java io模型浅谈

 acceptor事件处理(client connect)

   

java io模型浅谈


Read Write io事件NioHandler处理(这里展示client连接上了,就发送ping  ,server收到会用pong)

向selector注册read 事件

java io模型浅谈

selector 当read准备好后,会通过reactor的将read事件 分发到此handler(reactor代码的dispatch方法),这里将读写事件在同一个handler中进行处理。

java io模型浅谈

以上为简单的nio reactor模型的实现,大家可以对照button click 流程进行理解。



NIO(reactor 多线程模型)

         在上面的单线程reactor模型中,所有io事件处理都是一个线程中进行,对于一些小容量应用场景,可以使用单线程模型。但是对于高负载、大并发的应用场景却不合适。

       work Thread 线程池:reactor只负责分发io事件,事件处理由work Thread处理。下图可以看到,hander收到读写事件后,先可以放入一个queue中,保证io 线程的处理效率,在通过一个thread pool,来消费task queue中的事件。

         

java io模型浅谈


多reacotr 线程:上面的方案中,reactor io线程还是只有一个,对于高负载、大并发的应用场景仍会无法满足。


可以直接在acceptor中对于不同的client 连接注册到到对应的selector中,这样每个连接上上来的client可以注册到对应的selector中,使用对应的io thread 来处理io事件:

     

     

    本篇文章主要从设计思路上面介绍nio reactor原理,大名鼎鼎的netty框架其实也是按照reacotr模型进行设计,大家在了解reactor模型的基础上,可以看下netty的原理,有时间可以和大家分享下,可以达到更好的效果。

以上是关于java io模型浅谈的主要内容,如果未能解决你的问题,请参考以下文章

Java 四种IO模型

图解Java IO模型

浅谈Netty中ServerBootstrap服务端源码(含bind全流程)

Java IO模型:BIONIOAIO

JAVA - IO模型

《JDK源码分析》IO模型详解:第一章:IO模型演进(JAVA 小虚竹)