已经存在多种技术用于构建流处理系统。 其中包括用于 持久存储流数据 (例如 事件中心和Kafka)的系统,以及用于通过流数据表达 计算作 的系统(例如 Azure 流分析、 Apache Storm 和 Apache Spark 流式处理)。 这些是一流的系统,可用于生成高效的数据流处理管道。
现有系统的限制
但是,这些系统不适合 通过流数据进行细粒度自由格式计算。 上述流式处理计算系统允许你指定 以相同的方式应用于所有流项的统一操作数据流图。 这是一个强大的模型,当数据是均匀的,并且你想对此数据执行相同的转换、筛选或聚合操作时。 但是,其他用例需要对不同的数据项进行本质上不同的操作。 在这些情况下,在处理过程中,有时可能需要进行外部调用,例如调用任意 REST API。 统一数据流处理引擎要么不支持这些方案,要么以受限的方式支持它们,要么支持它们效率低下。 这是因为它们本质上针对 大量类似项目进行优化,并且通常限制在表达性和处理方面。 Orleans 数据流针对这些其他场景。
动机
这一切都是从用户请求 Orleans 开始的,以支持从粒度方法调用返回一系列项。 正如你想象的,这只是冰山的一角:他们需要更多。
流的一个典型方案 Orleans 是,你有每个用户流,并希望在该单个用户的上下文中 对每个用户执行不同的处理 。 你可能拥有数百万用户,但有些用户对天气感兴趣,并订阅特定位置的天气警报,而另一些用户则对体育赛事感兴趣;其他人可能会跟踪特定航班的状态。 处理这些事件需要不同的逻辑,但你不希望运行两个独立的流处理实例。 某些用户可能只对特定股票感兴趣,并且仅当某个外部条件适用时,该条件可能不一定是流数据的一部分(因此需要在运行时动态检查作为处理的一部分)。
用户经常更改他们的兴趣,因此他们对特定事件流的订阅会动态变化。 因此, 流式处理拓扑会动态和快速变化。 除此之外, 每个用户的处理逻辑会根据用户状态和外部事件动态变化和变化。 外部事件可能会修改特定用户的处理逻辑。 例如,在游戏作弊检测系统中,发现新的作弊方法时,处理逻辑需要使用新规则进行更新以检测此冲突。 当然,必须在不中断正在进行的处理流程的情况下完成。 批量数据流处理引擎不是为了支持此类方案而构建的。
几乎毋庸置疑,这种系统必须运行在多台联网的计算机上,而不仅仅是单个节点。 因此,处理逻辑必须跨服务器群集进行缩放和弹性分发。
新要求
为流处理系统确定了四个基本要求,以针对上述方案:
- 灵活的流处理逻辑
- 支持高度动态拓扑
- 细粒度流粒度
- 分销
灵活的流处理逻辑
系统应支持以不同的方式表达流处理逻辑。 上述现有系统要求开发人员编写声明性数据流计算图,通常遵循功能编程样式。 这限制了处理逻辑的表达性和灵活性。 Orleans 流对处理逻辑的表达方式漠不关心。 它可以表示为数据流(例如, 在 .NET 中使用反应扩展(Rx)、功能程序、声明性查询或常规命令逻辑。 逻辑可以是有状态的或无状态的,可能有副作用,也可能没有副作用,并且可以触发外部动作。 所有权力都归于开发者。
支持动态拓扑
系统应允许动态演变的拓扑。 上述现有系统通常仅限于在部署时固定的静态拓扑,这些拓扑在运行时无法演变。 在数据流表达式的以下示例中,一切正常且简单,直到需要更改它:
Stream.GroupBy(x=> x.key).Extract(x=>x.field).Select(x=>x+2).AverageWindow(x, 5sec).Where(x=>x > 0.8) *
更改筛选器中的 Where 阈值条件、添加 Select 语句或在数据流图中添加另一个分支并生成新的输出流。 在现有系统中,如果不拆毁整个拓扑并从头开始重启数据流,就不可能这样做。 实际上,这些系统会检查现有计算,并且可以从最新的检查点重启。 不过,对于产生实时结果的联机服务来说,这种重启是破坏性的,成本高昂。 在处理大量以类似但不同的参数(每用户、每设备等)执行的此类表达式时,这种重启变得特别不切实际。这些表达式会不断更改。
系统应允许在运行时演变流处理图,方法是将新的链接或节点添加到计算图或更改计算节点中的处理逻辑。
细粒度流粒度
在现有系统中,抽象的最小单位通常是整个流(拓扑)。 但是,许多目标方案要求拓扑中的单个节点/链接是逻辑实体本身。 这样,每个实体都可以独立管理。 例如,在包含多个链接的大型流拓扑中,不同的链接可以具有不同的特征,并通过不同的物理传输实现。 某些链接可能通过 TCP 套接字,而另一些则使用可靠的队列。 不同的链接可以有不同的传递保证。 不同的节点可以有不同的检查点策略,其处理逻辑可以以不同的模型甚至不同的语言表示。 这种灵活性通常无法在现有系统中实现。
抽象和灵活性参数的单位类似于比较 SoA(面向服务的体系结构)与执行组件。 执行组件系统允许更大的灵活性,因为每个执行组件本质上都是独立管理的“微小服务”。同样,流系统应允许这种细粒度的控制。
分销
当然,系统应该具有 “良好的分布式系统”的所有属性。 这包括:
- 可伸缩性:支持大量流和计算元素。
- 弹性:允许根据负载添加/删除资源以增长/收缩。
- 可靠性:抗故障能力强。
- 效率:有效使用基础资源。
- 响应能力:支持准实时场景。
这些是构建 Orleans 流式处理的要求。
说明: Orleans 目前不支持编写声明性数据流表达式,如上面的示例所示。 当前的Orleans流式处理 API 是更底层的构建模块,如Orleans流式处理 API 中所述。