我在上一篇的分享《Leader/Follower多线程网络模型介绍》中详细介绍了LF多线程网络模型的原理和代码分析。它的思路是减少线程上下文切换和数据拷贝时间,通过角色转换,来提高处理效率,尤其适用于处理短暂的、原子的并且反复的动作中的事件。可能大家都比较熟悉这种常用的思路了,那就是分层。它的核心思想:通过把异步和同步分开,用异步的方式来处理底层网络问题,用同步的方式来简化应用服务流程,通过合理的配合,达到提升效率的目的。
1、 引言
大家知道,通常高并发软件的服务处理,包括我们的旺旺,都是异步和同步同时存在的。异步用于高效地处理底层系统服务,同步则用于简化应用服务处理。要想从两种编程模型中均获益,高效地协调异步和同步服务处理是非常重要的。异步和同步服务处理通常是相关联的。例如,Web服务器的I/O层往往使用异步读操作来取得HTTP Get请求。而在CGI层对GET请求的处理则同步地运行于独立的控制线程。在I/O层异步到达的请求必须通过一种方法与CGI层对请求的同步处理集成在一起。换一个角度,我们再来看看Web客户端,AJAX可以使用异步JavaScript和XML来提高Web客户端的可感知响应速度。通常,异步和同步服务应该相互协作、取长补短。
2、 基本思想
本文介绍的HSHA方法,即HALF-SYNC/HALF-ASYNC模式,将并发软件的服务分解为异步和同步两层,然后增加一个队列层来处理二者直接的交互。使用单独的线程或者进程以同步的方式处理高层服务,比如领域功能、数据查询或文件传输,而底层系统服务则应该采用异步方式。
HALF-SYNC/HALF-ASYNC模式对这三层进行了严格的划分,这使得并发软件更容易理解、调试和改进。而且,异步和同步服务各自的缺陷也不会出现相互传染:异步服务的性能不会因为同步服务被阻塞而降低,同步服务的编程简单性也不会受到异步复杂性的影响。最后,使用排队层可以避免对异步和同步服务层之间的依赖进行硬编码,同时也可以简化消息处理的优先级排序。异步层和同步层的严格解耦合要求这两层之间的通信必须:
1)使用COPIED VALUES——这样就会带来性能上的损失和资源管理上的消耗,因为有更多的数据需要传送;
2)使用IMMUTABLE VALUES——这种做法相对来说属于轻量级的方式,但是其构造上可能更为复杂。
总的来说,HALF-SYNC/HALF-ASYNC通过使用层的概念来保证三个不同层的执行模型和通信模型的独立性和封装性。
同步层服务,比如数据库查询、文件传输或者领域功能通常运行在自己的线程中,以便多个服务可以同时执行。
异步层的服务可以通过异步中断或者支持异步I/O的操作系统API实现,后者包括Windows overlapped I/O和I/O完成端口(I/O completion ports),或者POSIX异步I/O系统调用。如果我们将HALF-SYNC/HALF-ASYNC设计成与PROACTOR或者REACTOR事件处理基础设施联合使用,这个事件处理基础设施便是所谓的异步层。虽然REACTOR并非是真正的异步,但如果它的服务实现的是短暂(short-duration)