• Reactor、Mina和Netty的NIO线程模型



    Reactor线程模型

           Reactor是反应堆的意思,Reactor模式即Dispatcher模式,服务器程序处理传入的多路请求,将他们同步分派给各请求对应的处理线程。

           Reactor有两个关键角色:

            Reactor Reactor在一个单独线程中运行,负责监听和分发事件,将请求事件分发给处理线程来对IO事件作出反应。

            Handlers 处理程序执行IO事件完成响应的事件操作。


    cmd-markdown-logo


    根据Reactor和Handler数量的不同,Reactor模型有3个变种。

    1. 单Reactor单线程
    2. 单Reactor多线程
    3. 主从Reactor多线程

    主从Reactor多线程包含MainReactor和SubReactor。MainReactor负责接收请求,并转发给SubReactor,SubSReactor负责相应通道的读写请求。非IO请求的任

    务直接写入工作队列,并等待Worker Thread处理。


    cmd-markdown-logo


    Mina线程模型


           在MINA中,有三种非常重要的线程:Acceptor thread、Connector thread、I/O processor thread。

            Acceptor thread:这个线程用于TCP服务器接收新的连接,并将连接分配到I/O processor thread,由I/O processor thread来处理IO操作。每个NioSocketAcceptor创建一个Acceptor thread,线程数量不可配置。


            Connector thread:用于处理TCP客户端连接到服务器,并将连接分配到I/O processor thread,由I/O processor thread来处理IO操作。每个NioSocketConnector创建一个Connector thread,线程数量不可配置。


           I/O processor thread:用于处理TCP连接的I/O操作,如read、write。I/O processor thread线程数量可通过NioSocketAcceptor或NioSocketConnector构造方法来配置,默认是CPU核心数+1。


           MINA的TCP服务器包含一个Acceptor thread和多个I/O processor thread,当有新的客户端连接到服务器,首先会由Acceptor thread获取到这个连接,同时将这个连接分配给多个I/O processor thread中的一个线程,当客户端发送数据给服务器,对应的I/O processor thread负责读取这个数据,并执行IoFilterChain中的IoFilter以及IoHandle。


           由于I/O processor thread本身数量有限,通常就那么几个,但是又要处理成千上万个连接的IO操作,如果有耗时、阻塞的任务,例如查询数据库,那么就会阻塞I/O processor thread,导致无法及时处理其他IO事件,服务器性能下降。针对这个问题,MINA中提供了一个ExecutorFilter,用于将需要执行很长时间的会阻塞I/O processor thread的业务逻辑放到另外的线程中,这样就不会阻塞I/O processor thread,不会影响IO操作。


    Netty的线程模型

           Netty是目前流行的由JBOSS提供的一个Java开源框架NIO框架,Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。Netty无疑是NIO的老大,它的健壮性、功能、性能、可定制性和可扩展性在同类框架都是首屈一指的。它已经得到成百上千的商业/商用项目验证,如Hadoop的RPC框架Avro、RocketMQ以及主流的分布式通信框架Dubbo等等。


           Netty基于JDK自带的NIO的API进行封装,相比JDK原生NIO,Netty提供了相对十分简单易用的API,非常适合网络编程。Netty是完全基于NIO实现的,所以Netty是异步的。Netty同时是基于主从Reactor多线程模型实现,借鉴了MainReactor和SubReactor结构。作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。

    Netty的优点可以总结如下:

    1. API使用简单,开发门槛低;

    2. 功能强大,预置了多种编解码功能,支持多种主流协议;

    3. 定制能力强,可以通过ChannelHandler对通信框架进行灵活地扩展;

    4. 性能高,通过与其他业界主流的NIO框架对比,Netty的综合性能最优;

    5. 成熟、稳定,Netty修复了已经发现的所有JDK NIO BUG,业务开发人员不需要再为NIO的BUG而烦恼;

    6. 社区活跃,版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会加入;

    7. 经历了大规模的商业应用考验,质量得到验证。在互联网、大数据、网络游戏、企业应用、电信软件等众多行业得到成功商用,证明了它已经完全能够满足不同行业的商业应用了。

    Netty服务端的创建方式如下:

    EventLoopGroup bossGroup = new NioEventLoopGroup();
    EventLoopGroup workGroup = new NioEventLoopGroup();
    ServerBootstrap server = new ServerBootstrap();
    server.group(bossGroup, bossGroup)
          .channel(NioServerSocketChannel.class);
    

    BossGroup和WorkGroup均是线程池

    • BossGroup线程池在绑定某个端口后,从BossGroup线程池获取一个线程作为MainReactor后处理端口的accept事件,一个端口对应一个boss。如果只监听一个端口,则BossGroup线程组只创建一个线程即可。
    • WorkGroup线程会被SubReactor和worker线程充分利用。

    Netty的关键组件如下:

    • BootStrap、ServerBootStrap

      Boostrap客户端启动引导类,ServerBootstrap服务端启动引导类,Bootstrap负责配置整改Netty,并串联起各个组件。

    • Channel

      Netty网络通信的组件,能够用于执行网络IO操作。

    • Selector

      Netty基于Selector对象实现I/O多路复用,通过 Selector, 一个线程可以监听多个连接的Channel事件, 当向一个Selector中注册Channel 后,Selector 内部的机制就可以自动不断地查询(select) 这些注册的Channel是否有已就绪的I/O事件(例如可读, 可写, 网络连接完成等)。

    • NioEventLoop

      NioEventLoop中维护一个线程和任务队列,支持异步提交任务,线程启动时会调用NioEventLoop的run方法,执行IO和非IO任务。 其中IO任务由prossSelectedKeys触发,非IO任务由runAlltasks触发。

    • NioEventLoopGroup

      NioEventLoopGroup用来管理EventLoop,可以理解为线程组,内部维护了一组线程。


    Netty的工作架构图如下:

    cmd-markdown-logo


    初始化netty服务端的过程如下:

    1. 初始化创建2个NioEventLoopGroup,其中bossGroup用于Accetpt连接建立事件并分发请求,workerGroup用于处理I/O读写事件和业务逻辑。
    2. 基于ServerBootstrap(服务端启动引导类),配置EventLoopGroup、Channel类型,连接参数、配置入站、出站事件handler。
    3. 绑定端口,开始工作。

           server端包含1个Boss NioEventLoopGroup和1个Worker NioEventLoopGroup,NioEventLoopGroup相当

    于1个事件循环组,这个组里包含多个事件循环NioEventLoop,每个NioEventLoop包含1个selector和1个事件循环线程。


    每个Boss NioEventLoop循环执行的任务包含3步

    1. 轮询accept事件
    2. 处理accept I/O事件,与Client建立连接,生成NioSocketChannel,并将NioSocketChannel注册到某个Worker NioEventLoop的Selector上
    3. runAllTasks处理任务队列中的非IO任务。

    每个Worker NioEventLoop循环执行的任务包含3步:

    1. 轮询read、write事件
    2. 处I/O事件,即read、write事件,在NioSocketChannel可读、可写事件发生时进行处理
    3. runAllTasks处理任务队列中的非IO任务。

    总结:

           1. Netty的TCP服务器启动时会创建两个NioEventLoopGroup,一个boss,一个worker。NioEventLoopGroup实际是是一个线程组,可通过构造函数设置线程数,默认是CPU核数*2。

           2. 当有新的TCP连接到服务器时,将有boss线程负责接收,然后将其注册到worder线程,worker线程负责处理IO操作,如read、write。当客户端数据发送到服务端时,worker负责接收数据,并执行ChannelPipeline的ChannelHandler方法。


    Netty和Mina比较

           mina与netty都是Trustin Lee的作品,所以在很多方面都十分相似,他们线程模型也是基本一致,采用了Reactors in threads模型,即Main Reactor + Sub Reactors的模式。

    1. 都是Trustin Lee的作品,Netty更晚;

    2. Mina将内核和一些特性的联系过于紧密,使得用户在不需要这些特性的时候无法脱离,相比下性能会有所下降,Netty解决了这个设计问题;

    3. Netty的文档更清晰,很多Mina的特性在Netty里都有;

    4. Netty更新周期更短,新版本的发布比较快;

    5. 它们的架构差别不大,Mina靠apache生存,而Netty靠jboss,和jboss的结合度非常高,Netty有对google protocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi);

    6. Netty比Mina使用起来更简单,Netty里你可以自定义的处理upstream events或/和downstream events,可以使用decoder和encoder来解码和编码发送内容;

    7. Netty和Mina在处理UDP时有一些不同,Netty将UDP无连接的特性暴露出来;而Mina对UDP进行了高级层次的抽象,可以把UDP当成”面向连接”的协议,而要Netty做到这一点比较困难。

    8. Netty中的boss线程类似于MINA的Acceptor thread,work线程和MINA的I/O processor thread类似。不同的一点是MINA的Acceptor thread是单个线程,而Netty的boss是一个线程组。

  • 相关阅读:
    【Oracle】dba_jobs字段说明
    【工作杂记】一次修改表字段名操作导致的报表缺失了2个小时的数据
    【SAP BO】无法识别账户信息:无法访问CMS。计算机上的CMS由于某个严重错误而停止。(FWM 20031)
    【虚拟机】在VMware中安装Server2008之后配置网络连接的几种方式
    vlc for android 编译过程
    ubuntu19更新源
    nginx错误Too many open files
    mp4流化
    编译ffmpeg的时候出现ERROR: libx264 not found
    nginx中Lua模块内置变量
  • 原文地址:https://www.cnblogs.com/qingfengEthan/p/12228245.html
Copyright © 2020-2023  润新知