学习整理
https://www.cnblogs.com/me115/p/4452801.html
https://blog.csdn.net/u013354486/article/details/82086084?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param
https://blog.csdn.net/ciddk2085/article/details/100620749?utm_medium=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase&depth_1-utm_source=distribute.pc_relevant_download.none-task-blog-baidujs-1.nonecase
Reactor
Reactor包含如下角色:
Handle 句柄;用来标识socket连接或是打开文件;
Synchronous Event Demultiplexer:同步事件多路分解器:由操作系统内核实现的一个函数;用于阻塞等待发生在句柄集合上的一个或多个事件;(如select/epoll;)
Event Handler:事件处理接口,拥有io文件句柄(可以通过get_handle获取,以及对handle的操作handle_event(读/写))
Concrete Event HandlerA:实现应用程序所提供的特定事件处理逻辑;
Reactor:反应器,定义一个接口,实现以下功能:
1)供应用程序注册和删除关注的事件句柄;
2)使用handle_events运行事件循环;
3)reactor不断调用Synchronous Event Demultiplexer的select函数,有文件句柄被激活,select就会返回,handle_events会调用与文件句柄关联的事件处理器handle_event进行处理
io多路复用的流程方式:
通过Reactor的方式,可以将用户线程轮询IO操作状态的工作统一交给handle_events事件循环进行处理,用户线程注册事件处理器之后可以继续执行做其他的工作(异步),而Reactor线程负责调用内核的select函数检查socket状态。当有socket被激活时,则通知相应的用户线程(或执行用户线程的回调函数),执行handle_event进行数据读取、处理的工作。
因为select系统调用是阻塞的,所以io多路复用并不是真正的异步,只能称为异步阻塞io
补充回顾:
大致流程:acceptor收到了客户端的tcp的链接。建立成功后,通过dispatch将对应的bytebuf分发到指定的handler上,进行消息解码
单线程出现的问题:
1.一个nio线程无法处理太多的链接,即便cpu满负荷也不可以
2.nio负载过重,处理速度会变慢
3.一旦nio线程跑飞,整个系统的通信模块都会变得不可用
Reactor多线程模型
不同处:acceptor作为一个单独的nio线程监听服务端,接收client的request
2.网络io操作读写由一个nio线程池负责,一个队列和多个可用的线程,这些线程负责消息的编解码及发送
3.一个nio线程可以同时处理多个链路,但是一个链路只对应一个nio线程
存在的问题:acceptor作为一个线程,如果出现大批量的client的访问,也会出现性能不足的情况,第三种模式 主从reactor
主从Reactor多线程模型
最大的特点就是接收客户端连接的不是一个单独的nio操作而是变成了一个独立的nio线程池
这个接收线程池收到请求并处理完以后会创建一个新的socketchannel然后注册到sub线程池的io上,然后由sub线程池中的对socketchannel中的数据进行编解码操作
总结:acceptor线程池仅仅用于客户端的登录握手等安全认证,建立成功以后就将链路注册到后端的subReactor线程池的io线程上,由io线程负责后续的io操作
netty的官方demo 推荐使用该线程模型 传送 ============>
https://www.jianshu.com/writer#/notebooks/48158437/notes/88605230/writing
Proactor:
主要区别一句话总结:reactor是内核告诉用户进程文件句柄状态,用户线程去内核去进行读取及处理数据的操作;proactor是内核将数据读取完,并且将内核中的数据复制到用户线程指定的缓存区域,告诉用户线程直接去处理。
几个接口的概念
Handle 句柄;用来标识socket连接或是打开文件;
Asynchronous Operation Processor:异步操作处理器;负责执行异步操作,一般由操作系统内核实现;
Asynchronous Operation:异步操作
Proactor:主动器;为应用程序进程提供事件循环;从完成事件队列中取出异步操作的结果,分发调用相应的后续处理逻辑;
Completion Handler:完成事件接口;一般是由回调函数组成的接口;
Concrete Completion Handler:完成事件处理逻辑;实现接口定义特定的应用处理逻辑;
大致实现流程:用户线程将Asynchronous Operation / Proactor / Completion Handler 注册到Asynchronous Operation Processor(异步操作处理器);然后异步操作处理器就会使用Facade提供的异步操作api供用户使用,异步操作处理器会开启独立的内核线程执行异步操作,操作结束以后处理器会将complehandler和处理完的io数据一起给Proactor,由proactor调用不同的完成事件接口的handle_event()
过程:用户线程直接调用proactor提供的异步api进行read请求,就是完成上面的注册过程。当read请求的数据到达时,由内核负责读取socket中的数据,并写入用户指定的缓冲区中。最后内核将read的数据和用户线程注册的CompletionHandler分发给内部Proactor,Proactor将IO完成的信息通知给用户线程