Reactor模型是非阻塞的同步IO模型。在主线程中也就是IO处理单元中,只负责监听文件描述符上是否有事件发生,有的话就立即将事件通知工作线程,将socket可读可写事件放入请求队列,交给工作线程处理。
总而言之就是主线程监听有事件发生后,就需要在应用程序中主动调用read方法来完成数据的数去,也就是要应用程序主动将socket接收缓存中的数据读取到应用进程内存中,在这个过程是同步的,读取完数据后应用进程才能处理数据。
同步的意思就是应用程序去操作系统读取数据,异步是操作系统直接将数据写到我们提供的buf中然后通知应用进程。
在Reactor模式中还细分了几个模式:单Reactor单线程,单Reactor多线程以及主从Reactor模式。
1. 单reactor单线程模型就是使⽤ I/O 多路复⽤技术,当其获取到活动的事件列表时,就在reactor中进⾏读取请 求、业务处理、返回响应,这样的好处是整个模型都使⽤⼀个线程,不存在资源的争夺问题。但是如果⼀个事 件的业务处理太过耗时,会导致后续所有的事件都得不到处理。
2. 单reactor多线程就是⽤于解决这个问题,这个模型中reactor中只负责数据的接收和发送reactor将业务处 理分给线程池中的线程进⾏处理,完成后将数据返回给reactor进⾏发送,避免了在reactor进⾏业务处理,但 是 IO 操作都在reactor中进⾏,容易存在性能问题。⽽且因为是多线程,线程池中每个线程完成业务后都需要 将结果传递给reactor进⾏发送,还会涉及到共享数据的互斥和保护机制。
3. 主从reactor就是将reactor分为主reactor和从reactor,主reactor中只负责连接的建⽴和分配,读取请求、 业务处理、返回响应等耗时的操作均在从reactor中处理,能够有效地应对⾼并发的场合。
proactor模式
将所有的IO操作都交给主线程和内核来处理,工作线程仅仅负责业务逻辑。主线程调用异步IO的API向内核注册socket上的读写事件,并告诉内核用户读缓存区的位置,以及读操作完成时应该如何通知应用进程。然后主线程继续其他逻辑。当socket有数据被读入用户缓存区的时候,内核向应用程序发送一个信号,然后执行业务逻辑。
简单的说就是发起异步读写请求时,需要传入数据缓存区的地址和通知信号,这样系统内核才可以自动帮我们把数据的读写工作完成,这里的读写工作都是由操作系统来做的,不需要像Reactor那样需要应用进程主动发起read/write来读写数据。
那么为什么不用proactor模型呢?
在linux下异步IO是不完善的,不是真正的操作系统级别支持的,而是在用户空间模拟出来的异步。仅仅支持基于本地文件的aio异步操作,网络编程中的socket是不支持的。