【后端开发】Reactor 模型详解
研究背景
其实我们在研究 netty 的时候我们必定绕不过 NIO 的,也必定必须研究一下这个 Reactor 模型的,如果不进行这个 Reactor 模型和 NIO 知识点的研究,那么我们必定掌握不了 Netty 的精髓,为什么呢?
因为 Netty 底层封装的就是 NIO 的代码,如果 NIO 的三大组件比如 channel、buffer、以及 selector 不搞清楚的话那么指定是搞不懂 Netty 的,即使掌握了也是 API 层面的
Reactor 模型简直是太经典了,Netty 的模型是三种经典的 Reactor 模型演化过来的,而且不仅仅是 Netty 有这个模型,Redis、Nginx 等有名的中间件都是借鉴了这个模型的思想
Reactor 模型
核心思想
Reactor 模型的核心是 Reactor 加上对应的处理器 Handler,Reactor 在一个单独的线程中运行,负责监听和分发事件,将接收到的事件交给不同的 Handler 来处理,Handler 是处理程序执行 I/O 事件的实际操作
基础类型
我们先说说基础的客户端服务端传统模型,这里 BIO 是最原生的代表,也是因为效率比较低下之后衍生出来了 NIO 的模型
BIO 模型
经典的类型就是 BIO 模型,一个客户端过来进行请求连接,那么服务端就需要进行创建一个线程进行处理链接请求,这种就是少量的客户端的话还可以,如果当大量的客户端如果进行连接请求的话,那么就会造成服务端的线程资源紧缺,而且这个过程服务器和客户端两边都是阻塞的状态,而且传统的 BIO 模式还存在同步效率低的问题,如果建立了链接,服务端就傻等着客户端发来请求,如果没有请求过来,那么这个线程一直在阻塞着,就造成了资源的浪费
图解
案例代码
NIO 模型
上面的 BIO 模式就是效率低下的阻塞 IO,而 NIO 是基于事件驱动的 IO 模型,他这种方式就好很多了,他不会进行线程的阻塞,因为他是有一个专门负责事件轮询的 selector 选择器进行 channel 通道监听,如果有事件发生那么就进行相应的事件处理就可以了, 更多详情可以阅读我之前写的 NIO 系列的文章
【文章福利】另外小编还整理了一些 C++后台开发教学视频,相关面试题,后台学习路线图免费分享,需要的可以自行添加:Q群:720209036 点击加入~ 群文件共享
小编强力推荐 C++后台开发免费学习地址:C/C++Linux服务器开发高级架构师/C++后台开发架构师
图解
案例代码
这种方式就可以通过一个线程来进行接收客户端的所有链接请求,之后监听所有的链接通道 channel,如果有相应事件发生那么就进行对应的相应事件处理,比如读事件、连接请求事件等等
单 Reactor 单线程模型
生活中的例子
酒店的前台,当前的这种情况就是前台和服务员是同一个人,全程一个人进行服务,效率会非常的低下,后面新来的客人只能在大厅等待了,客户的体验也不好
模型详解
上面的 NIO 代码就是单 Reactor 单线程模型的,确实是一个 selector 监听轮询所有的 channel 不假,但是如果真正的多数据量处理读写请求的时候他也是堵塞在那里等待着 handler 处理完才能进行处理下一个请求,所以这种场景只适合小数据量的处理,瞬间完成或者是毫秒级完成才能达到高效率缺点:
高并发复杂数据处理的时候效率不高性能低下,容易造成堵塞效果
由于是单线程所以发挥不出来多核心的效果
优点:
模型简单、不存在线程并发的时候造成数据不安全的问题
图解
单 Reactor 多线程模型
生活中的例子
此时就是一个前台接待员对应多个前台的服务员了,这样的话前台的接待员专门对接就是接待客人的任务,后面的工作任务都是其他服务员的,这样其他的客人来了能进行及时的接待,即使间隔比较短的来人,那么也是稍等一小会儿就可以了
模型详解
单线程模型其实就是进行数据逻辑处理的时候效率比较低下,那我们可以将单线程改成多线程,那么就是还是一个 Reactor 中的 selector 进行事件监听,之后 Acceptor 进行处理客户端的连接请求,创建一个 Handler 进行该连接请求的后续处理工作,但是这个 Hanlder 只是负责事件的响应操作,真正的业务逻辑处理还是直接交给了后续的线程池去处理,线程池将任务完成后返回给 Handler,之后 Handler 将处理好的结果返回给客户端缺点:
大并发上来的时候还是会存在性能瓶颈的问题
在并发场景下会存在数据安全性的问题
优点:
多线程可以充分的利用了系统的 CPU 资源
图解
主从 Reactor 多线程模型
生活中的例子
这种就是接待员只负责类似喊句话的操作,欢迎光临这种,之后就将其交给了其他的接待员进行处理了,比如订房间等等、之后剩下的工作任务交给其他的服务员,比如端茶倒水带领客户去对应的房间,这样客户体验感会更好,能处理客户的需求更快
模型详解
主从模式就是,Reactor 的主线程模型通过 selector 进行连接事件监听,收到的如果是连接事件的话,那么用 Acceptor 进行连接事件处理,之后将创建好的连接事件交给 Reactor 子线程进行处理【Reactor 主线程和 Reactor 子线程是一对多的关系】,此时子线程将连接加入到连接队列进行事件监听,如果发生了其他事件比如读事件,那么 Reactor 子线程就会调用相应的 Handler 进行事件处理,handler 进行数据读取后复杂的业务也是交给后面的线程池进行业务处理并返回结果,Handler 接收到处理结果后返回给客户端缺点:
高并发的时候依旧存在数据安全性问题
编码起来比较繁琐
优点:
能够处理高并发、吞吐量大、效率高、结构之间分工明确 netty 其实就是这种场景的演化
图解
总结
Reactor 模型具有如下优点
响应速度快,不必为单个同步事件所阻塞,因为是事件轮询机制
可以最大程度的避免复杂的多线程及同步问题,并且避免了多线程/进程的切换开销
扩展性好,可以方便的通过增加 Reactor 实例个数来充分利用 CPU 资源
复用性好,Reactor 模型本身与具体事件处理逻辑无关,具有很高的复用性
Reactor 模型具有如下缺点
相比传统的简单模型,Reactor 增加了一定的复杂性,因而有一定的门槛,并且不易于调试。想要掌握 netty 那么就必须掌握这个模型的机制。
参考资料
推荐一个零声教育 C/C++后台开发的免费公开课程,个人觉得老师讲得不错,分享给大家:C/C++后台开发高级架构师,内容包括Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习
评论