zoukankan      html  css  js  c++  java
  • Netty-6、Netty 线程模型

    1 Proactor和Reactor

    Proactor和Reactor是两种经典的多路复用I/O模型,主要用于在高并发、高吞吐量的环境中进行I/O处理。

    I/O多路复用机制都依赖于一个事件分发器,事件分离器把接收到的客户事件分发到不同的事件处理器中,如下图:

    1.1 select,poll,epoll

    在操作系统级别select,poll,epoll是3个常用的I/O多路复用机制,简单了解一下将有助于我们理解Proactor和Reactor。

    1.1.1 select

    select的原理如下:

    用户程序发起读操作后,将阻塞查询读数据是否可用,直到内核准备好数据后,用户程序才会真正的读取数据。

    poll与select的原理相似,用户程序都要阻塞查询事件是否就绪,但poll没有最大文件描述符的限制。

    1.1.2 epoll

    epoll是select和poll的改进,原理图如下:

    epoll使用“事件”的方式通知用户程序数据就绪,并且使用内存拷贝的方式使用户程序直接读取内核准备好的数据,不用再读取数据

    1.2 Proactor

    Proactor是一个异步I/O的多路复用模型,原理图如下:

    • 用户发起IO操作到事件分离器
    • 事件分离器通知操作系统进行IO操作
    • 操作系统将数据存放到数据缓存区
    • 操作系统通知分发器IO完成
    • 分离器将事件分发至相应的事件处理器
    • 事件处理器直接读取数据缓存区内的数据进行处理

    1.3 Reactor

    Reactor是一个同步的I/O多路复用模型,它没有Proactor模式那么复杂,原理图如下:

    • 用户发起IO操作到事件分离器
    • 事件分离器调用相应的处理器处理事件
    • 事件处理完成,事件分离器获得控制权,继续相应处理

    1.4 Proactor和Reactor的比较

    • Reactor模型简单,Proactor复杂
    • Reactor是同步处理方式,Proactor是异步处理方式
    • Proactor的IO事件依赖操作系统,操作系统须支持异步IO
    • 同步与异步是相对于服务端与IO事件来说的,Proactor通过操作系统异步来完成IO操作,当IO完成后通知事件分离器,而Reactor需要自己完成IO操作

    2 Reactor多线程模型

    前面已经简单介绍了Proactor和Reactor模型,在实际中Proactor由于需要操作系统的支持,实现的案例不多,有兴趣的可以看一下Boost Asio的实现,我们主要说一下Reactor模型,Netty也是使用Reactor实现的。

    但单线程的Reactor模型每一个用户事件都在一个线程中执行:

    • 性能有极限,不能处理成百上千的事件
    • 当负荷达到一定程度时,性能将会下降
    • 单某一个事件处理器发送故障,不能继续处理其他事件

    2.1 多线程Reactor

    使用线程池的技术来处理I/O操作,原理图如下:

    • Acceptor专门用来监听接收客户端的请求
    • I/O读写操作由线程池进行负责
    • 每个线程可以同时处理几个链路请求,但一个链路请求只能在一个线程中进行处理

    2.2 主从多线程Reactor

    在多线程Reactor中只有一个Acceptor,如果出现登录、认证等耗性能的操作,这时就会有单点性能问题,因此产生了主从Reactor多线程模型,原理如下:

    • Acceptor不再是一个单独的NIO线程,而是一个独立的NIO线程池
    • Acceptor处理完后,将事件注册到IO线程池的某个线程上
    • IO线程继续完成后续的IO操作
    • Acceptor仅仅完成登录、握手和安全认证等操作,IO操作和业务处理依然在后面的从线程中完成

    3 Netty中Reactor模型的实现

    Netty同时支持Reactor的单线程、多线程和主从多线程模型,在不同的应用中通过启动参数的配置来启动不同的线程模型。

    通过线程池的线程个数、是否共享线程池方式来切换不同的模型

    3.1 Netty中的Reactor模型

    Netty中的Reactor模型如下图:

    • Acceptor中的NioEventLoop用于接收TCP连接,初始化参数
    • I/O线程池中的NioEventLoop异步读取通信对端的数据报,发送读事件到channel
    • 异步发送消息到对端,调用channel的消息发送接口
    • 执行系统调用Task
    • 执行定时Task

    3.2 NioEventLoop

    NioEventLoop是Netty的Reactor线程,它在Netty Reactor线程模型中的职责如下:

    1. 作为服务端Acceptor线程,负责处理客户端的请求接入
    2. 作为客户端Connecor线程,负责注册监听连接操作位,用于判断异步连接结果
    3. 作为IO线程,监听网络读操作位,负责从SocketChannel中读取报文
    4. 作为IO线程,负责向SocketChannel写入报文发送给对方,如果发生写半包,会自动注册监听写事件,用于后续继续发送半包数据,直到数据全部发送完成

    如下图,是一个NioEventLoop的处理链:

    • 处理链中的处理方法是串行化执行的
    • 一个客户端连接只注册到一个NioEventLoop上,避免了多个IO线程并发操作

    3.2.1 Task

    Netty Reactor线程模型中有两种Task:系统Task和定时Task
    • 系统Task:创建它们的主要原因是,当IO线程和用户线程都在操作同一个资源时,为了防止并发操作时锁的竞争问题,将用户线程封装为一个Task,在IO线程负责执行,实现局部无锁化
    • 定时Task:主要用于监控和检查等定时动作

    基于以上原因,NioEventLoop不是一个纯粹的IO线程,它还会负责用户线程的调度

    3.2.2 IO线程的分配细节

    线程池对IO线程进行资源管理,是通过EventLoopGroup实现的。线程池平均分配channel到所有的线程(循环方式实现,不是100%准确),一个线程在同一时间只会处理一个通道的IO操作,这种方式可以确保我们不需要关心同步问题。

    3.2.3 Selector

    NioEventLoop是Reactor的核心线程,那么它就就必须实现多路复用。

    Selector的过程如下:

    • 首先oldWakenUp = wakenUp.getAndSet(false)
    • 如果队列中有任务, selectNow()
    • 如果没有select(),直达channel准备就绪,但此过程中循环次数超过限值也将rebuidSelectoror退出循环
    • 执行processSelectedKeys和runAllTasks

    epoll-bug的处理

    在netty中对java nio的epoll bug进行了处理,就是设置一个阀值,如果超过了就rebuidSelector来避免epoll()死循环

    3.2.4 NioEevntLoopGroup

    EventExecutorGroup:提供管理EevntLoop的能力,他通过next()来为任务分配执行线程,同时也提供了shutdownGracefully这一优雅下线的接口

    EventLoopGroup继承了EventExecutorGroup接口,并新添了3个方法

    • EventLoop next()
    • ChannelFuture register(Channel channel)
    • ChannelFuture register(Channel channel, ChannelPromise promise)

    EventLoopGroup的实现中使用next().register(channel)来完成channel的注册,即将channel注册时就绑定了一个EventLoop,然后EvetLoop将channel注册到EventLoop的Selector上。

    NioEventLoopGroup还有几点需要注意:

    • NioEventLoopGroup下默认的NioEventLoop个数为cpu核数 * 2,因为有很多的io处理
    • NioEventLoop和java的single线程池在5里差异变大了,它本身不负责线程的创建销毁,而是由外部传入的线程池管理
    • channel和EventLoop是绑定的,即一旦连接被分配到EventLoop,其相关的I/O、编解码、超时处理都在同一个EventLoop中,这样可以确保这些操作都是线程安全的
     
     
  • 相关阅读:
    多测师讲解html _伪类选择器17_高级讲师肖sir
    多测师讲解html _后代选择器16_高级讲师肖sir
    多测师讲解html _组合选择器_高级讲师肖sir
    多测师讲解html _标签选择器14_高级讲师肖sir
    前端 HTML form表单标签 input标签 type属性 重置按钮 reset
    前端 HTML form表单标签 textarea标签 多行文本
    前端 HTML form表单标签 input标签 type属性 file 上传文件
    前端 HTML form表单标签 input标签 type属性 radio 单选框
    前端 HTML form表单标签 input标签 type属性 checkbox 多选框
    前端 HTML form表单目录
  • 原文地址:https://www.cnblogs.com/chenxiaoxian/p/10431835.html
Copyright © 2011-2022 走看看