描述:Reactor 对象通过 Select 监控客户端请求事件,收到事件后通过 Dispatch 进行分发,如果是建立连接请求事件,则由 Acceptor 通过 Accept 处理连接请求,然后创建一个 Handler 对象处理连接完成后的后续业务处理,如果不是建立连接事件,则 Reactor 会分发调用连接对应的 Handler 来响应,Handler 会完成 Read→业务处理→Send 的完整业务流程
优点:模型简单,没有多线程、进程通信、竞争的问题,全部都在一个线程中完成
缺点:性能问题,只有一个线程,无法完全发挥多核 CPU 的性能。Handler 在处理某个连接上的业务时,整个进程无法处理其他连接事件,很容易导致性能瓶颈
单 Reactor 多线程
描述:不同于单 Reactor 单线程的地方是Handler 只负责响应事件,不做具体业务处理,通过 Read 读取数据后,会分发给后面的 Worker 线程池进行业务处理,Worker 线程池会分配独立的线程完成真正的业务处理,Handler 收到响应结果后通过 Send 将响应结果返回给 Client
优点:可以充分利用多核 CPU 的处理能力
缺点:多线程数据共享和访问比较复杂;Reactor 承担所有事件的监听和响应,在单线程中运行,高并发场景下容易成为性能瓶颈
主从 Reactor 多线程
描述:Reactor 主线程 MainReactor 对象通过 Select 监控建立连接事件,收到建立连接事件后通过 Acceptor 接收,Acceptor 处理建立连接事件后,MainReactor 将连接分配 Reactor 子线程给 SubReactor 进行处理,SubReactor 将连接加入连接队列进行监听,并创建一个 Handler 用于处理各种连接事件,当有新的事件发生时,SubReactor 会调用连接对应的 Handler 进行响应,Handler 处理方式同单 Reactor 多线程
优点:主线程与子线程的数据交互简单职责明确,主线程线程只需要把新连接传给子线程,子线程完成后续的业务处理
****
Proactor 模型
Proactor 模型是异步网络模型 ,把 I/O 操作改为异步,即交给操作系统来完成就能进一步提升性能
描述:AsyOptProcessor 处理注册请求,并处理 I/O 操作,Proactor Initiator 创建 Proactor 和 Handler 对象,并将 Proactor 和 Handler 都通过 AsyOptProcessor(Asynchronous Operation Processor)注册到内核,AsyOptProcessor 完成 I/O 操作后通知 Proactor,Proactor 根据不同的事件类型回调不同的 Handler 进行业务处理,Handler 完成业务处理
优点:效率更高,异步 I/O 更加充分发挥 DMA(Direct Memory Access,直接内存存取)的优势
缺点:编程复杂性难以 Debug,内存使用,缓冲区在读或写操作的时间段内必须保持住,相比 Reactor 模式,在 Socket 已经准备好读或写前,是不要求开辟缓存的
I/O多路复用技术select、poll、epoll之间的区别select
单个进程所能打开的最大连接数有FD_SETSIZE宏定义,其大小是32个整数的大小(在32位的机器上,大小就是32 * 32,同理64位机器上FD_SETSIZE为32 * 64)
每次调用时都会对连接进行线性遍历,所以随着FD的增加会造成遍历速度慢的“线性下降性能问题”
内核需要将消息传递到用户空间,都需要内核拷贝动作
poll
poll本质上和select没有区别,但是它没有最大连接数的限制,原因是它是基于链表来存储的,其他性质同select
epoll
虽然连接数有上限,但是很大,1G内存的机器上可以打开10万左右的连接,2G内存的机器可以打开20万左右的连接
因为epoll内核中实现是根据每个fd上的callback函数来实现的,只有活跃的socket才会主动调用callback,所以在活跃socket较少的情况下,使用epoll没有前面两者的线性下降的性能问题,但是所有socket都很活跃的情况下,可能会有性能问题
epoll通过内核和用户空间共享一块内存来实现的消息传递
进程间共享内存的8种方式无名管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在父子进程间使用
高级管道(popen):将另一个程序当做一个新的进程在当前程序进程中启动,则它算是当前程序的子进程
有名管道 (named pipe) : 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信