NIO Reactor模型

NIO Reactor模型NIOReactor模型Reactor三种模型单线程模型多线程模型主从多线程模型Netty线程模型1线程组2ChannelPipeline3异步非阻塞Reactor模式是基于事件驱动开发的,服务端程序处理传入多路请求,并将它们同步分派给请求对应的处理线程,Reactor模式也叫Dispatcher模式,即I/O多路复用统一监听事件,收到事件后分发(Dispatch给某进程),这是编写高性能网络服务器的必备技术之一。Reactor模式以NIO为底层支持,核心组成部分包括Reactor和Ha

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

Reactor模式是基于事件驱动开发的,服务端程序处理传入多路请求,并将它们同步分派给请求对应的处理线程,Reactor模式也叫Dispatcher模式,即I/O多路复用统一监听事件,收到事件后分发(Dispatch给某进程),这是编写高性能网络服务器的必备技术之一。

Reactor模式以NIO为底层支持,核心组成部分包括Reactor和Handler:

  • Reactor:Reactor在一个单独的线程中运行,负责监听和分发事件,分发给适当的处理程序来对I/O事件做出反应。它就像公司的电话接线员,它接听来自客户的电话并将线路转移到适当的联系人。

  • Handlers:处理程序执行I/O事件要完成的实际事件,Reactor通过调度适当的处理程序来响应 I/O 事件,处理程序执行非阻塞操作。类似于客户想要与之交谈的公司中的实际员工。

Reactor三种模型

根据Reactor的数量和Handler线程数量,可以将Reactor分为三种模型:

  • 单线程模型 (单Reactor单线程)
  • 多线程模型 (单Reactor多线程)
  • 主从多线程模型 (多Reactor多线程)

单线程模型

在这里插入图片描述
Reactor内部通过Selector监控连接事件,收到事件后通过dispatch进行分发,如果是连接建立的事件,则由Acceptor处理,Acceptor通过accept接受连接,并创建一个Handler来处理连接后续的各种事件,如果是读写事件,直接调用连接对应的Handler来处理。

Handler完成read -> (decode -> compute -> encode) ->send的业务流程。

这种模型好处是简单,坏处却很明显,当某个Handler阻塞时,会导致其他客户端的handler和accpetor都得不到执行,无法做到高性能,只适用于业务处理非常快速的场景,如redis读写操作。

多线程模型

在这里插入图片描述
主线程中,Reactor对象通过Selector监控连接事件,收到事件后通过dispatch进行分发,如果是连接建立事件,则由Acceptor处理,Acceptor通过accept接收连接,并创建一个Handler来处理后续事件,而Handler只负责响应事件,不进行业务操作,也就是只进行read读取数据和write写出数据,业务处理交给一个线程池进行处理。

线程池分配一个线程完成真正的业务处理,然后将响应结果交给主进程的Handler处理,Handler将结果send给client。

单Reactor承担所有事件的监听和响应,而当我们的服务端遇到大量的客户端同时进行连接,或者在请求连接时执行一些耗时操作,比如身份认证,权限检查等,这种瞬时的高并发就容易成为性能瓶颈。

主从多线程模型

在这里插入图片描述
存在多个Reactor,每个Reactor都有自己的Selector选择器,线程和dispatch。

主线程中的mainReactor通过自己的Selector监控连接建立事件,收到事件后通过Accpetor接收,将新的连接分配给某个子线程。

子线程中的subReactor将mainReactor分配的连接加入连接队列中通过自己的Selector进行监听,并创建一个Handler用于处理后续事件。

Handler完成read -> 业务处理 -> send的完整业务流程。

Netty线程模型

Netty线程模型就是Reactor模式的一个实现,如下图所示:
在这里插入图片描述

1 线程组

Netty抽象了两组线程池BossGroup和WorkerGroup,其类型都是NioEventLoopGroup,BossGroup用来接受客户端发来的连接,WorkerGroup则负责对完成TCP三次握手的连接进行处理。

NioEventLoopGroup里面包含了多个NioEventLoop,管理NioEventLoop的生命周期。每个NioEventLoop中包含了一个NIO Selector、一个队列、一个线程;其中线程用来做轮询注册到Selector上的Channel的读写事件和对投递到队列里面的事件进行处理。

Boss NioEventLoop线程的执行步骤:

  • 处理accept事件, 与client建立连接, 生成NioSocketChannel。

  • 将NioSocketChannel注册到某个worker NIOEventLoop上的selector。

  • 处理任务队列的任务, 即runAllTasks。

Worker NioEventLoop线程的执行步骤:

  • 轮询注册到自己Selector上的所有NioSocketChannel的read和write事件。

  • 处理read和write事件,在对应NioSocketChannel处理业务。

  • runAllTasks处理任务队列TaskQueue的任务,一些耗时的业务处理可以放入TaskQueue中慢慢处理,这样不影响数据在pipeline中的流动处理。

Worker NIOEventLoop处理NioSocketChannel业务时,使用了pipeline (管道),管道中维护了handler处理器链表,用来处理channel中的数据。

2 ChannelPipeline

Netty将Channel的数据管道抽象为ChannelPipeline,消息在ChannelPipline中流动和传递。ChannelPipeline持有I/O事件拦截器ChannelHandler的双向链表,由ChannelHandler对I/O事件进行拦截和处理,可以方便的新增和删除ChannelHandler来实现不同的业务逻辑定制,不需要对已有的ChannelHandler进行修改,能够实现对修改封闭和对扩展的支持。

ChannelPipeline是一系列的ChannelHandler实例,流经一个Channel的入站和出站事件可以被ChannelPipeline 拦截。每当一个新的Channel被创建了,都会建立一个新的ChannelPipeline并绑定到该Channel上,这个关联是永久性的;Channel既不能附上另一个ChannelPipeline也不能分离当前这个。这些都由Netty负责完成,而无需开发人员的特别处理。

根据起源,一个事件将由ChannelInboundHandler或ChannelOutboundHandler处理,ChannelHandlerContext实现转发或传播到下一个ChannelHandler。一个ChannelHandler处理程序可以通知ChannelPipeline中的下一个ChannelHandler执行。Read事件(入站事件)和write事件(出站事件)使用相同的pipeline,入站事件会从链表head 往后传递到最后一个入站的handler,出站事件会从链表tail往前传递到最前一个出站的 handler,两种类型的 handler 互不干扰。

在这里插入图片描述
ChannelInboundHandler回调方法:
在这里插入图片描述
ChannelOutboundHandler回调方法:
在这里插入图片描述

3 异步非阻塞

写操作:通过NioSocketChannel的write方法向连接里面写入数据时候是非阻塞的,马上会返回,即使调用写入的线程是我们的业务线程。Netty通过在ChannelPipeline中判断调用NioSocketChannel的write的调用线程是不是其对应的NioEventLoop中的线程,如果发现不是则会把写入请求封装为WriteTask投递到其对应的NioEventLoop中的队列里面,然后等其对应的NioEventLoop中的线程轮询读写事件时候,将其从队列里面取出来执行。

读操作:当从NioSocketChannel中读取数据时候,并不是需要业务线程阻塞等待,而是等NioEventLoop中的IO轮询线程发现Selector上有数据就绪时,通过事件通知方式来通知业务数据已就绪,可以来读取并处理了。

每个NioSocketChannel对应的读写事件都是在其对应的NioEventLoop管理的单线程内执行,对同一个NioSocketChannel不存在并发读写,所以无需加锁处理。

使用Netty框架进行网络通信时,当我们发起I/O请求后会马上返回,而不会阻塞我们的业务调用线程;如果想要获取请求的响应结果,也不需要业务调用线程使用阻塞的方式来等待,而是当响应结果出来的时候,使用I/O线程异步通知业务的方式,所以在整个请求 -> 响应过程中业务线程不会由于阻塞等待而不能干其他事情。

转载
I/O与Netty原理精讲

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/234377.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • yuicompressor java_YUI Compressor使用配置方法 JS/CSS压缩工具

    yuicompressor java_YUI Compressor使用配置方法 JS/CSS压缩工具YUICompressor是一个用来压缩JS和CSS文件的工具,采用Java开发。YUICompressor下载地址:https://www.jb51.net/softs/25860.html使用方法://压缩JSjava-jaryuicompressor-2.4.2.jar–typejs–charsetutf-8-vsrc.js>packed.js//…

    2022年7月18日
    19
  • 语音芯片,语音合成芯片,嵌入式语音合成软件的区别

    语音芯片,语音合成芯片,嵌入式语音合成软件的区别在当前科技发达,越来越智能的时代,追求产品体验更好,人机交互带有语音播报越来越成为一种时尚。无论是家用产品,还是室外公共设备,市场上带有语音提示和语音预警的产品也与日俱增,越来越受到消费者的青睐,语音功能让产品更智能,极大的增强了用户的产品体验。除了手机,平板等智能设备外,在智能家居等产品上要实现语音播报功能,有以下3种解决方案,我们逐一进行介绍。

    2022年6月26日
    25
  • Tarjan_com.pakdata.QuranMajeed

    Tarjan_com.pakdata.QuranMajeedTarjanTarjan是一种求有向图强联通分量的算法,是用dfs实现以及时间戳标记访问最短时间的.Tarjan算法中每个点都需要扩展边,为了存储方便,推荐使用邻接表.Tarjan算法的优势在于其灵活性,基础代码可以直接适用于多数情况.常见于dfs序.

    2025年7月15日
    3
  • Oracle数据库备份与还原

    Oracle数据库备份与还原Oracle数据库备份与还原一、逻辑备份1.某一用户(DBA权限)全库备份:2.某一用户(DBA权限)备份库中某些用户:3.某一用户备份自身:4.某一用户备份自身某些表对象:5.某一用户(具有DBA权限)备份其他用户某些表对象:二、逻辑还原1.使用全库备份文件还原:①使用全库备份文件还原库:②使用全库备份文件还原库内某些用户(被还原用户应存在):③使用全库备份文件还原库内某些用户某些表:2.使用某些用户备份文件还原:①使用某些用户备份文件还原库内某些用户(被还原用户应存在):②使用某些用户备份文件还原库内某

    2022年7月12日
    19
  • Linux中创建自己的MOTD[通俗易懂]

    Linux中创建自己的MOTD[通俗易懂]1)什么是MOTDmotd:是英文缩写messageoftheday。译文是:每日提示信息,问候报文。那你为什么要用MOTD?其实目的很简单,是提示进入系统的用户注意事项,或提示系统运行的概

    2022年8月3日
    28
  • LG手机锁屏删除韩国时间_动态时钟锁屏

    LG手机锁屏删除韩国时间_动态时钟锁屏打开开发者模式,usb调试。连接电脑,命令行输入adbshellsettingsputsecureroaming_dualclock1adbshellsettingsputsecureskt_roaming_dualclock1如果显示等待手机连接,把手机连接电脑方式改为充电或图片,传输文件模式下usb调试连接不上国外完整版命令地址,可以删除预装软件…

    2022年9月29日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号