Reactor模式总结

1. 网络编程的抽象

网络编程可以抽象为以下步骤:

  • 读请求(read request)
  • 读解析(read decode)
  • 处理程序(process service)
  • 应答编码 (encode reply)
  • 发送应答(send reply)

最古老的模式就是单线程处理,服务端阻塞在套接字,来一个请求依次跑一遍流程,每个请求依次排队处理, 这种方式在互联网时代已经完全无法应付了。
改进一下,每当来一个请求,都开启一个线程去处理(或者更好一点,用一个线程池),但是依然存在问题:当客户端多,并发数较大时,需要创建大量线程来处理连接,系统资源占用较大。 同时,连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在read操作上,造成线程资源浪费。
I1Fw7T.png 解决read阻塞问题的最简单的方式是将 read 操作改为非阻塞,然后进程不断地轮询多个连接。 这种方式能够解决阻塞的问题,但解决的方式并不优雅。首先,轮询是要消耗 CPU 的;其次,如果一个进程处理几千上万的连接,则轮询的效率是很低的。更好的方式是只有连接上有数据时才去处理,这就是IO多路复用。

2. IO多路复用

I1kvs1.png

使用一个线程来检查多个文件描述符的就绪状态,比如调用select和epoll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行。
这样在处理多个个连接时,只需要1个线程监控就绪状态,对就绪的每个连接开一个线程处理就可以了,这样需要的线程数大大减少,减少了内存开销和上下文切换的CPU开销。

3. Reactor的几种模式

Reactor的核心就是I/O多路复用统一监听事件,收到事件后分发给相应的进程或线程处理。
在这个处理流程中包含如下角色:

  • Reactor 将I/O事件发派给对应的Handler
  • Acceptor 处理客户端连接请求
  • Handlers 执行非阻塞读/写

3.1 单Reactor单线程

I1me56.png

Reactor通过select监控客户端请求事件,收到事件后通过dispatch进行分发,如果是建立连接请求事件,则由Acceptor通过accept处理连接请求, 然后创建一个Handler对象处理连接完成后的后续业务处理, 如果不是建立连接事件,则Reactor会分发调用连接对应的Handler来响应,handler完成读取处理发送的全部逻辑。这种模型简单,没有多线程、进程通信、竞争的问题,全部都在一个线程中完成。 但是Handler在处理某个连接上的业务时,整个进程无法处理其他连接事件,很容易导致性能瓶颈。Redis就是使用这种模式。

3.2 单Reactor多线程

I1ns6e.png

Reactor对象通过select监控客户端请求事件,收到事件后通过dispatch进行分发,如果是建立连接请求事件,则由Acceptor通过accept处理连接请求, 然后创建一个Handler对象处理连接完成后的续各种事件,如果不是建立连接事件,则Reactor会分发调用连接对应的Handler来响应 ,Handler只负责响应事件,不做具体业务处理,通过read读取数据后,会分发给后面的Worker线程池进行业务处理 ,Worker线程池会分配独立的线程完成真正的业务处理,将响应结果发给Handler进行处理 ,Handler收到处理结果响应客户端。这种模式可以充分利用多核CPU的处理能力,但是模型复杂,多线程数据共享和访问比较复杂。如果子线程完成业务处理后,把结果传递给主线程Reactor进行发送,就会涉及共享数据的互斥和保护机制。

3.3 多Reactor多线程

I1ui7R.png

Reactor主线程MainReactor对象通过select监控建立连接事件,收到事件后通过Acceptor接收,处理建立连接事件, Acceptor处理建立连接事件后,MainReactor将连接分配Reactor子线程给SubReactor进行处理 ,SubReactor将连接加入连接队列进行监听,并创建一个Handler用于处理各种连接事件, 当有新的事件发生时,SubReactor会调用连接对应的Handler进行响应,Handler通过read读取数据后,会分发给后面的Worker线程池进行业务处理 ,Worker线程池会分配独立的线程完成真正的业务处理,如何将响应结果发给Handler进行处理,Handler收到处理结果响应客户端。这种模式父线程与子线程的数据交互简单职责明确,父线程只需要接收新连接,子线程完成后续的业务处理。 这种模式应用广泛,比如netty和nginx(多进程)。

如果觉得我的文章对您有用,请在支付宝公益平台找个项目捐点钱。 @sxzhou Dec 11, 2020

奉献爱心