服务器设计模式
1、半同步半异步模式
简而言之,所谓的半同步半异步模式分为三个组成模块:同步处理模块,队列模块,异步处理模块.三个模块之间的交互关系如图:
几个模块的之间的交互为:异步模块接收可能会异步到来的各种事件(I/O,信号等),然后将它们放入队列中,而同步模块一般只有一种动作,就是不停的从队列中取出消息进行处理.
半同步-半异步模式的出现是为了给服务器的功能进行划分,尽可能将的可能阻塞的操作放在同步模块中,这样不会影响到异步模块的处理.
2、Leader-Follower模型
2.1、基本思想
所有线程会有三种身份中的一种:leader和follower,以及一个干活中的状态:proccesser。它的基本原则就是,永远最多只有一个leader。而所有follower都在等待成为leader。线程池启动时会自动产生一个Leader负责等待网络IO事件,当有一个事件产生时,Leader线程首先通知一个Follower线程将其提拔为新的Leader,然后自己就去干活了,去处理这个网络事件,处理完毕后加入Follower线程等待队列,等待下次成为Leader。这种方法可以增强CPU高速缓存相似性,及消除动态内存分配和线程间的数据交换。
2.2、原理分析
显然地,通过预先分配一个线程池,Leader/Follower设计避免了动态线程创建和销毁的额外开销。将线程放在一个自组织的池中,而且无需交换数据,这种方式将上下文切换、同步、数据移动和动态内存管理的开销都降到了最低。
不过,这种模式在处理短暂的、原子的、反复的和基于事件的动作上可以取得明显的性能提升,比如接收和分发网络事件或者向数据库存储大量数据记录。事件处理程序所提供的服务越多,其体积也就越大,而处理一个请求所需的时间越长,池中的线程占用的资源也就越多,同时也需要更多的线程。相应的,应用程序中其它功能可用的资源也就越少,从而影响到应用程序的总体性能、吞吐量、可扩展性和可用性。
在大多数LEADER/FOLLOWERS设计中共享的事件源封装在一个分配器组件中。如果在一个设计中联合使用了LEADER/FOLLOWERS和REACTOR事件处理基础设施,由reactor组件进行分发。封装事件源将事件分离和分派机制与事件处理程序隔离开来。每个线程有两个方法:一个是join方法,使用这个方法可以把新初始化的线程加入到池中。新加入的线程将自己的执行挂起到线程池监听者条件(monitor condition)上,并开始等待被提升为新的Leader。在它变成一个Leader之后,它便可以访问共享的事件源,等待执行下一个到来的事件。另一个是promote_new_leader方法,当前的Leader线程使用这个方法可以提升新的Leader,其做法是通过线程池监听者条件通知休眠的Follower。收到通知的Follower继续执行(resume)线程池的join方法,访问共享事件源,并等待下一个事件的到来。
3、Reactor 和 Proactor
- Linux用reactor模拟异步,跟proactor不一样的是,proactor将IO完成事件放入队列等待处理,demultiplexer阻塞在该队列,而reactor则将IO就绪事件放入队列,demultiplexer也阻塞在该队列,只不过proactor直接处理hook,而reactor的模拟还需要先进行数据IO。
- reactor和proactor是一类概念,处理的是网络连接并发问题,半同步半异步跟领导者跟随者是一类概念,面对的是网络连接之后,如何用线程池来处理后台各类任务。