SEDA: An Architecture for Well-Conditioned, Scalable Internet Services
Abstract
Staged Event-Driven Architecture(SEDA)是一种新的高并发Internet服务设计,旨在支持大量并发需求,并简化条件良好的服务的构造。在SEDA中,应用程序由显式队列连接的事件驱动阶段(event-driven stage)网络组成。
SEDA利用一组动态资源控制器(dynamic resource controllers ),在负载波动较大的情况下,让各个stage内部保证稳定运行,防止在需求超过服务能力时过度使用资源。我们设计了几种用于自动调优和负载调节的控制机制:线程池大小调整、事件批处理和自适应减载。
1 Introduction
本文描述了一个基于SEDA的互联网服务平台的设计、架构和实现。该平台提供高效、可扩展的I/O接口以及多种资源控制机制,包括线程池大小和动态事件调度。
SEDA的目标是:在负载发生巨大变化的情况下,能保持多数服务的健壮性,同时易于编程。
要提高服务的可伸缩性(scalability),复制(Replication)是一个传统的重头戏。对于一个服务实例来说,当负载成倍增长,那就必须对其重新配置,才能维持这个服务性能的稳定。但是,假如我们假设每个节点都会经历较大的负载峰值,由于峰值负载可能远远大于平均负载,因此复制不能处理最大的潜在需求。
传统操作系统为了提供最大的透明度,为每个进程提供一个虚拟机的抽象,该虚拟机具有自己的CPU、内存、磁盘和网络。这在某种程度上与互联网服务的需求不符,互联网服务需要大量的一致性和对资源使用的广泛控制。
因此尽管进程和线程是很好的并发编程模型,但在高并发环境下,上下文切换和内存占用会导致极大开销,从而限制并发性。对于对于特定服务来说,会有相应的方法保证它们的性能和健壮性,而SEDA的目标是实现一个通用的解决方案。
SEDA结合了基于线程和基于事件的编程模型,以管理Internet服务的并发性、I/O、调度和资源管理需求。在SEDA中,应用程序被构造为a network of stages,每个阶段都有一个相关的传入事件队列。每个stage模块保证自身的健壮,当服务量可能超过自身处理能力的时候,可以通过设置阈值或事件过滤来单独调节加载。并且,应用程序可以根据事件队列的状态获取网络内部的状况,做出相应的调度和资源管理决策,例如重新排序、过滤或聚合请求。SEDA利用动态资源流量控制(dynamic resource throttling)控制应用程序组件的资源分配和调度,允许系统适应过载条件。
2 Background and Related Work
SEDA两个重要的研究方向:使用基于线程的并发模型简化编程,使用基于事件的并发模型实现高并发。
本节通过概述导致SEDA设计的步骤中的关键贡献和问题来开发这种方法的沿袭。直观地说,如果一个服务表现得像一个简单的管道(pipeline),那么它就是well-conditioned,其中管道的深度是由通过网络的路径和服务本身的处理阶段决定的。
随着所提供的负载的增加,所交付的吞吐量会成比例地增加,直到管道满了,吞吐量达到饱和;附加负载不应降低吞吐量。类似地,服务显示的响应时间在轻负荷下大致恒定,因为它是由管道的深度决定的。当负载接近饱和时,排队延迟占主导地位。
在许多服务的典型闭环场景中,每个客户端在交付下一个请求之前等待响应,响应时间应该随着客户端数量的增加而线性增加。而对于传统的Web来说,当负载增加时,吞吐量降低,响应时间显著增加,造成服务崩溃。well-conditioned服务一定要能graceful degradation(高效处理崩溃):当提供的负载超过容量时,服务仍旧能以线性响应时间代价维持高吞吐量,对所有clients的影响是相同的,或者至少基于一些特定服务的策略能够预测这个代价。
2.1 线程并发 Thread-based concurrency
下图简要描述了基于线程的并发:每个传入请求被分配给一个单独的线程,该线程处理请求并将结果返回给客户端。这里没有显示其他I/O操作,如磁盘访问,但是将合并到每个线程的请求处理中。
服务器应用程序最常用的设计是thread-per-re