服务器高并发设计模式

首先要区分并发和并行的概念,并发强调能够处理多个事务的能力,而并行是指同时能够处理多个事务。这里主要讨论高并发下,我们如何利用对程序进行合理的设计,提高系统的并发性。

半同步/半异步模式

在并发模式下,同步和异步的概念与I/O同步异步的概念有所不同,这里的同步是指程序按照代码的顺序执行,而异步指的是程序的执行需要系统事件来驱动,比如信号、中断等。


异步线程效率高,但编写相对复杂,难于调式,而同步线程刚好相反,逻辑简单,但效率较差。
半同步/半异步模式结合了同步线程和异步线程的优点,它在处理I/O事件时使用异步线程,处理客户逻辑则使用同步线程。这样既满足了客户连接的实时性,又能同时处理多个连接。
实现半同步/半异步需要三个模块:异步处理模块、同步处理模块和队列模块
在实际的应用中,一般使用I/O复用epoll在主线程上监听客户端的连接,一旦监听到新的客户请求后,将其封装成请求对象,插入到队列中,同时,很多工作线程可以来读取并处理该请求对象。
在这个模式中,最可能阻塞的操作放在同步模块中,这样不会影响到异步模块的处理,不同模块可以使用不同的同步策略,互不干扰,模块间通信则使用IPC实现,但这样则会造成同步模块和异步模块使用队列模块传送数据的时候,由于数据拷贝和上下文切换导致的性能开销。


半同步/半反应堆模式


半同步/半反应堆模式是半同步/半异步模式的一个变体,在半同步/半异步模式中,工作线程如何选择队列中的请求,是事先设计好的。而在半同步/半反应堆模式中,工作线程通过竞争(例如申请互斥锁)来获得任务的接管权。
半同步/半反应堆可以采用Reactor模式,也可以采用Proactor模式处理,另外两种I/O模式的区别参考:I/O设计模式
半同步/半反应堆中,异步线程是主线程,负责监听所有的socket事件,如果监听socket上有可读事件发生,指的是新的连接到来,那么异步线程接受它,插入到请求队列中,空闲工作线程开始竞争任务,之后这个线程管理这个socket的所有I/O任务,直到客户关闭连接,工作线程各自监听管理不同的事件,所以不需要通信,每个线程都是异步模式。
缺点:对此进行队列操作是,都需要加锁解锁,从而消耗CPU事件,另外一个线程同一时间只能处理一个客户请求,如果队列中积累了很多任务,如果增加工作线程,工作线程的切换也会耗费大量CPU时间。
改进:工作线程可以调用epoll_wait,这样一个工作线程也可以处理多个客户请求。


领导者/追随者模式

领导者/追随者模式是指多个工作线程轮流监听、分发、处理事件的一种模式。在任意事件,程序都仅有一个领导者线程,它负责监听I/O事件。其他线程都是追随者,他们休眠在线程池中等待新的领导者。当领导者检测到I/O事件时,首先从线程池中选出新的领导者线程,然后处理I/O事件。此时,新的领导者等待新的I/O事件,旧的领导者处理I/O事件,实现并发。
领导者/追随者最大的优点在于,它是自己监听I/O事件并处理客户请求,也就是说从接收到处理都是在同一线程中完成,所以不需要在线程之间传递任何额外的数据,也不用在线程间同步对队列的访问。但也有一个明显的缺点,就是只支持一种事件源集合,所以导致它不能像其他模式让每个线程独立处理不同的客户请求。


参考资料
服务器高并发设计模式
半同步/半异步模式和领导者/追随者模式