========================================================================
线程模型的学习对于理解Netty是比不可少的,我们从线程模型的演变一步一步来讲解
首选是传统的BIO线程模型,这个在第一章我们有过了解,它的特点是:
-
一个请求需要创建一个线程去处理
-
如果read不到数据,线程会阻塞
所以这种线程模型导致的问题就是
-
高并发场景下会频繁创建很多线程,频繁的创建和销毁线程对系统性能损耗非常大
-
read不到数据线程进行阻塞,这导致线程资源的浪费
Reactor(也叫Dispacher)线程模型不再为每个请求创建线程 ,而是基于 I/O 复用模型,多个请求连接同一个阻塞对象,应用程序只需要在一个阻塞对象等待,无需阻塞等待所有连接。当请求中有数据,操作系统通知应用程序,线程从阻塞状态返回,开始进行业务处理,一个线程可以处理多个连接的业务,如图:
先来理解两个概念
-
Reactor:即图中的ServiceHandler,Reactor负责监听和事件分发,分发给适当的处理程序来对 IO 事件做出反应, 在单独的线程中执行。就像公司的电话接线员,它接听来自客户的电话并将线路转移到适当的联系人;
-
Handlers:Reactor监听到IO事件,需要调度应用程序来处理即:Handler,Handler是真正处理 I/O 事件的程序,类似于接电话的实际的人员。
简单理解就是Reactor线程模型有两个角色 ,一个负责接待请求(Reactor), 一个负责处理请求(Handlers)
Reactor单线程
另外Reactor有三种模式 :Reactor 单线程模型 、单 Reactor 多线程模型 、
Reactor主从多线程模型 。Netty框架是基于主从Reactor多线程模型进行改进(多个主Reactor)。 下面是Reactor单线程模型,如图:
Reactor单线程模型工作流程如下
-
Reactor 通过 Select 监控客户端请求,收到事件后通过 Dispatch 进行请求分发
-
如果是请求事件是建立连接,则由 Acceptor 通过 accept 处理连接请求,然后创建一个 Handler 。
-
如果不是连接事件,则 Reactor 会分发调用连接对应的 Handler 来处理请求
-
Handler 会完成数据read,进行业务处理最后通过 Send 将响应结果返回给 Client
Reactor单线程模型优点是模型简单,缺点也是比较明显
-
线程单一,如果并发高,业务处理慢,很容易导致性能瓶颈,
-
如果线程故障或终止,整个系统不可用
所以这种模型不太适合高并发场景,和业务处理比较耗时的场景。
Reactor多线程
接下来看一下单Reactor 多线程模型 ,先看图把:
Reactor多线程模式工作流程如下
-
Reactor 通过 Select 监控客户端请求,收到事件后通过 Dispatch 进行请求分发
-
如果是请求事件是建立连接,则由 Acceptor 通过 accept 处理连接请求,然后创建一个 Handler 。
-
如果不是连接事件,则 Reactor 会分发调用连接对应的 Handler 来处理请求
-
Handler 只负责响应事件,不做具体业务处理,通过 Read 读取数据后,会分发给后面的 Worker 线程池进行业务处理
-
Worker 线程池会分配独立的线程完成真正的业务处理,将响应结果发给 Handler 进行处理。
-
Handler 收到响应结果后通过 Send 将响应结果返回给 Client。
这种模型引入了线程池,Reactor线程负责接收连接和响应事件,具体IO事件交给线程池分配的线程处理。优点是可以充分利用CPU,提供整体性能,但是Reactor承担所有的事件监听和分发,容易成为性能瓶颈,多线程的数据共享也是一个问题。
主从Reactor多线程
单Reactor多线程的问题是Reactor在单线程中执行可能会成为瓶颈,那么主从Reactor多线程就解决了这个问题 ,看图:
主从Reactor多线程模式工作流程如下
-
Reactor 主线程 MainReactor 对象通过 Select 监听连接事件,收到事件后通过 Acceptor 接收,处理建立连接事件。
-
Acceptor 处理建立连接事件后,MainReactor 将连接分配 Reactor 子线程给 SubReactor 进行处理。
-
SubReactor 将连接加入连接队列进行监听,并创建一个 Handler 用于处理各种连接事件,
-
当有新的事件发生时,SubReactor 会调用连接对应的 Handler 处理
-
Handler 通过 Read 读取数据后,会分发给后面的 Worker 线程池进行业务处理
-
Worker 线程池会分配独立的线程完成真正的业务处理,将响应结果发给 Handler 进行处理
-
Handler 收到响应结果后通过 Send 将响应结果返回给 Client
这种模式的优点比较明显,Reactor主线程只需要接收新连接,子线程完成后续的业务处理,Reactor的压力得到了分担。这种模型在许多项目中广泛使用,包括 Nginx 主从 Reactor 多进程模型,Memcached 主从多线程,Netty 主从多线程模型的支持。
========================================================================
Netty是基于主从Reactor多线程模型实现,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果,Netty线程模型如下图:
Netty线程模型中有两个Group,分别是Boss Group和Worker Group,的BossGroup 用于Accetpt连接建立事件并分发请求,workerGroup用于处理I/O读写事件和业务逻辑。其中关键组件如下
- Channel
Netty网络通信的组件,能够用于执行网络IO操作。
- Selector
Netty基于Selector对象实现I/O多路复用,即:一个线程可以监听多个连接的Channel事件, 当channel向Selector注册 后,Selector 就可以自动不断地查询(select) 注册的Channel是否有已就绪的I/O事件(例如可读, 可写, 网络连接完成等)。
- NioEventLoop
NioEventLoop表示一个不断循环的执行处理任务的线程, 每个NioEventLoop 都有一个 selector。用于监听注册的Channel的IO事件。
NioEventLoop中维护一个线程和任务队列,支持异步提交任务,线程启动时会调用NioEventLoop的run方法,执行IO和非IO任务。 其中IO任务由prossSelectedKeys触发,非IO任务由runAlltasks触发。
- NioEventLoopGroup
NioEventLoopGroup用来管理EventLoop,可以理解为线程组,内部维护了一组线程
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
我还通过一些渠道整理了一些大厂真实面试主要有:蚂蚁金服、拼多多、阿里云、百度、唯品会、携程、丰巢科技、乐信、软通动力、OPPO、银盛支付、中国平安等初,中级,高级Java面试题集合,附带超详细答案,希望能帮助到大家。
还有专门针对JVM、SPringBoot、SpringCloud、数据库、Linux、缓存、消息中间件、源码等相关面试题。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
33580)]
还有专门针对JVM、SPringBoot、SpringCloud、数据库、Linux、缓存、消息中间件、源码等相关面试题。
[外链图片转存中…(img-oxgE4VBI-1713467233581)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!