此文章由机器翻译。

Microsoft Azure

面向事件流系统的兴起

Christopher Bennage

它是所有关于数据这几天。数据可以帮助我们做出明智的决定。大数据帮助我们作出知情和有见地的决定。大的数据流的帮助我们做出知情的、 有见地的和及时的决策。这些不断流动的数据流通常被称为事件流。它是越来越多地共同打造软件系统,其主要目的是处理事件流。

甚至可以跨越不同的行业和领域,那里是可识别的常见建筑模式,围绕这些事件面向流的系统。这种模式为现代事件面向流的系统起着经典的 n 层体系结构为传统的对处所企业系统举行的相同的基本作用。我会开始探索这一新兴模式的缩略图。

模式识别

首先,我应该澄清术语事件什么意思。在这里,这意味着只是有点事情发生在一个系统中的数据。事件往往较小的大小以字节或千字节范围。你还会听到像消息、 遥测或甚至只是数据替代事件的条款。

接下来,有事件生产者。这些生产者可以是几乎任何东西 — — 连接汽车、 智能温控器、 游戏机、 个人健身设备或甚至软件系统生成自我-­诊断事件。它是重要的是认识到,虽然,在大部分的这些系统,你在跟许多事件生产者。

许多系统预期事件生产者在数万人,进千家万户的数以百万计或多个不等的数目。这意味着这些系统往往具有高容量和高速度。高容量意味着还有大量的全面和高速度意味着频繁地生成数据的数据。

另外还有事件使用者。消费者是这些类型的系统的真正核心。他们是负责分析、 解释和对事件的响应。在一个典型的系统中的消费者的数量可能范围从几个到一对夫妇打。事件不被路由到特定的消费者。每个消费者在看同一组事件。在微软 Azure 中,消费者是最有可能的云服务。

考虑一下这个例子。还有代表金融交易事件流。在这个场景中的事件生产者是零售商店的销售点系统。一个消费者拥有责任分析欺诈活动的流,并发出警报。另一位消费者分析相同的流,以使得时间只是供应链的优化。最后,第三的消费者负责事件转化为长期的冷库,为以后分析。

当结合现实的高容量与高-­速度事件生产者和消费者的这种模式将介绍几个有趣的问题:

  • 你如何防止事件生产潮从绝大多数消费者?那就是,该系统时如何响应事件产率开始超过消耗率?
  • 因为事件速度很高,你如何可以扩展单个事件消费者?

解决问题的关键是使用事件代理 (请参阅图 1)。这是精确地由最近发布 Azure 事件枢纽的作用。

天青事件集线器架构
图 1 天青事件集线器架构

那么如何,确切地说,不使用代理 (例如事件集线器解决我到目前为止已经概述的问题?

了解事件集线器

事件集线器提供吸收和保留事件,直到下游消费者能赶上所需的弹性。事件集线器可以有效地调配出变异事件中流率因此消费者不必担心这件事。无此流平性、 接收的消费者可能会变得不堪重负,开始失败。

使用代理隔离事件生产者和事件消费者从彼此。这种隔离是特别重要的体系结构模式的更成熟的版本附加的中介人有必要的生产者和消费者之间。事件集线器是组成、 煤层或体系结构中的边界点。通过事件集线器进行交互的所有组件不需要彼此的特定知识。

在这一点上,它可能容易混淆事件集线器与传统­消息提供隔离的相同类型的服务的国际企业。然而,事件集线器是不同的几个关键的方式,使这种建筑模式的理想选择。

独立的消费者

事件中心使用的是发布 / 订阅的模式 ; 然而,每个消费者都有相同的事件流的独立见解。在一些传统的消息传递系统与多个消费者,邮件被复制为每个感兴趣的消费者。这可能是低效的速度及空间,但好处是每个消费者都有它自己的"收件箱"。作为一个消费者处理消息,它会从其收件箱中移除它们。还有其他消费者没有影响,因为他们在他们自己的收件箱中有它们自己的副本。

与事件集线器,还有一套不可改变的事件,以及因为他们是不可变的只需要有一份副本的每个事件。同样,消费者永远不会从系统中删除事件。所有的消费者正在寻找相同的事件集。正因为如此,消费者自己跟踪的责任他们所在的地方在事件流中。他们这样做是通过跟踪他们在事件流中的偏移量。还有实际上为此 SDK 中内置的 API。

基于时间的保留

在传统的消息传递系统中,消费者是负责告知系统,它完成的消息时。然后,该系统可以摆脱消息。因为事件集线器消费者负责跟踪自己事件流内的位置,如何不事件集线器知道当消费者做的事件?总之,它不会。 与事件集线器,您将配置的保留期和事件存储的大量时间。这意味着事件届满对他们自己的独立于任何消费者行动。

基于时间的含义是保留的消费者的需求,检查并处理过期之前的事件。与基于时间的保留,每个消费者都有压力,保持。幸运的是,事件中心的基础设计允许个体消费者作为必要的规模。

支持这项活动枢纽由物理分区的事件流。资源调配事件集线器时设置分区的数。请参阅官方文档 bit.ly/11QAxOY 更多详细信息。

当事件发布到事件的中心,它们被放在分区中。某一特定的事件驻留在只有一个分区。事件是均匀分布在默认情况下中的轮循机制方式的分区。有提供分区关联的机制。最常见的允许您设置分区键属性的事件,并具有相同键的所有事件将都送交同一分区。

如何分区的事件流,帮助消费者与基于时间的保留?在事件集线器中,正确的说法是实际上的消费群体。称这一组的原因是每个消费者确实含有多个实例。每个组有一个实例,每个分区。从这一点上,消费群是指作为一个整体消费者和消费者实例是指一个特定分区中感兴趣的组的成员。

这意味着一个消费者团体可以处理并行流事件。组中的每个消费者实例可以处理一个分区独立于其他实例。这些消费者实例均可以驻留在一台机器,从另一个运行在隔离每个消费者实例。可以跨多台计算机,甚至到了每个消费者实例运行在一个专用的盒子上分发。这种方式,事件集线器绕过一些与竞争消费者的经典模式相关的典型问题。

隔离是一个关键的概念。第一,你孤立事件生产者和事件消费者从彼此,从而使灵活的体系结构组成以及负荷量。第二,消费群体是彼此,隔离整个消费群体减少连锁故障的机会。第三,消费者在一个给定的消费群体中的实例是,使水平方向上缩放为个人消费群体而彼此隔离。

使用事件集线器

有几个好的教程,入门事件集线器。查阅正式文件在 bit.ly/11QAxOY 和教程使用您所选择的平台。

您需要提供一个事件中心第一次。这个过程非常简单。你很容易可以把它尝试与审判的 Azure 帐户。在 Azure 管理门户中,导航到服务总线节。你将需要创建一个服务总线命名空间,如果你不已经有一个。在那之后,你会看到称为已说明,用于创建一个事件中心的事件集线器的一个选项卡 (见图 2)。

创建一个事件枢纽
图 2 创建一个事件枢纽

您还需要为事件枢纽设置一个共享的访问策略之前就可以开始。这些政策管理安全事件枢纽。在门户中,导航到您刚才创建的事件集线器并选择配置选项卡。

选择管理的权限,并为策略指定一个名称,如"超级"或"做-不-使用-中-生产"。在那之后,切换到仪表板选项卡,单击底部的连接信息按钮。你会想要注意到的连接字符串,以及你给你事件中心的名称。

生成事件

我会在这里显示的代码使用.NET SDK,但您可以使用任何支持 HTTP 或 AMQP 的平台。您将需要参考微软 Azure 服务总线 NuGet 程序包。你需要的类是 Microsoft.ServiceBus.Messaging 命名空间中。你需要做的就是创建一个客户端,创建一个事件并发送:

var client = EventHubClient.CreateFromConnectionString (
  connectionString,
  eventHubName);
var body = Encoding.UTF8.GetBytes("My first event");
var eventData = new EventData (body);
await client.SendAsync (eventData);

虽然简单,但有几个有趣的项目,指出。该事件的身体是只是一个字节数组。处理此事件的任何消费群体将需要知道如何解释这些字节为单位)。它是提示的可能的消费群体将需要某种形式,用来确定如何反序列化的身体。该事件被发送之前,可以附加元数据:

eventData.Properties.Add ("event-type", "utf8string");

这意味着使用键和值都是众所周知的生产者和消费者团体。如果你想要确保一组事件发送到同一分区,您可以设置分区键:

eventData.PartitionKey = "something-meaningful-to-your-domain";

如果事件不具有亲和力与分区,你会得到更好的性能。在某些情况下,虽然,你就会想一套相关的事件路由到一个单一消费者实例进行处理。要在他们收到的订单,保证具有给定分区中的事件。同样地,没有简单的方法,以保证事件的顺序在不同的分区,在事件的中心。这通常是永生永世事件动机要关联到一个特定的分区。

例如,如果您要启用智能汽车,你想为给定的车能在同一分区中的所有事件。您可能会选择分区键的车辆识别号码 (VIN)。或您的系统可能会集中在智能楼宇、 与数以百计的生产事件的每一幢楼房中的设备。在这种情况下,您可能使用建筑本身的身份为该分区键等所有事件从相同的建设用地在同一个分区中的所有设备。

总体来看,分区的亲和力是危险的做法,只应谨慎使用。分区键一个糟糕的选择可能导致一个不均匀的事件分配跨分区。这可能最终意味着消费群体会有麻烦的缩放比例。好消息是,很多时候,您可以更改系统的设计,以避免需要分区的亲和力。

使用事件

你可能会担心你会怎么这一切。你的顾客群体需要来跟踪其偏移量在事件流中。每个组需要有一个为每个分区的实例。幸运的是,还有的 API。

引用 NuGet 程序包微软 Azure 服务总线集线器事件­ProcessorHost。你需要的类是 Microsoft.ServiceBus.Messaging 命名空间中。入门很简单,只执行一个单一的界面:IEventProcessor。

一旦你实现了你的事件处理器,您将创建 EventProcessorHost 注册您的事件处理器的一个实例。主机将处理你所有的繁重工作。当它启动时,它将检查您的事件中心去看看它有多少个分区。然后,它将创建您为每个可用的分区的事件处理器的一个实例。

有三种方法,您需要实现。前两个是 OpenAsync 和 CloseAsync。宿主调用 OpenAsync 时事件处理器实例是第一批出分区。这意味着事件处理器实例具有独占访问权限到分区问题的消费群。同样,主机会丢失其租约时,或当它关闭时调用 CloseAsync。虽然你现在开始,您可以使用一个非常简单的实现:

public Task OpenAsync(PartitionContext context)
{
  return Task.FromResult(true);
}
public Task CloseAsync(PartitionContext context, CloseReason reason)
{
  return Task.FromResult(true);
}

这两种方法接收一个 PartitionContext 参数。剩余的方法以及接收。如果您想要查看有关特定的分区空间租给了事件处理器的详细信息,您可以检查此参数。最后一个方法是,在哪里你实际收到的事件 (见图 3)。

图 3 提供了事件的最终方法

public async Task ProcessEventsAsync (PartitionContext context, 
  IEnumerable<EventData> messages)
{
  foreach (var message in messages)
  {
    var eventType = message.Properties["event-type"];
    var bytes = message.GetBytes();
    if (eventType.ToString() == "utf8string") {
      var body = System.Text.Encoding.UTF8.GetString (bytes);
      // Do something interesting with the body
    } else {
      // Record that you don't know what to do with this event
    }
  }
  await context.CheckpointAsync();
  // This is not production-ready code
}

正如你所看到的这很简单。您会收到的事件你可以遍历或做任何工作需要的可枚举集合。您还可以调用的上下文。CheckpointAsync 方法的末尾。这就告诉主人你成功处理了这一组事件,您想要记录一个检查点。检查点是在批处理中的最后一个事件的偏移量。

这就是如何你消费群可以跟踪的每个分区已处理的事件。主机启动后,它尝试获取任何可用的分区的租约。当它开始处理为一个分区时,它将检查该分区的检查点信息。仅去年执行检查点操作的偏移量比更近的事件被发送到他们各自的处理器。

主机还提供自动负载调配跨机器。例如,假设您有事件枢纽,16 分区。这意味着将有 16 个实例的事件处理器 — — 一个用于每个分区。如果您在一台机器上运行主机,它在同一机器上创建所有 16 个实例。如果你在相同的消费群二机及其部分上启动另一台主机,两台主机将开始跨两个机级分布的事件处理器实例。最终将每台机器的八个事件处理器实例。同样地,如果你取下第二台机器,然后第一个主机接管回来的孤立的分区。

假设您的 IEventProcessor 的实现是 MyEventProcessor。然后实例化该主机可以是这么简单:

var host = new EventProcessorHost(
  hostName,
  eventHubName,
  consumerGroupName,
  eventHubConnectionString,
  checkpointConnectionString);
await host.RegisterEventProcessorAsync<MyEventProcessor>();

EventHubConnectionString 和 eventHubName 是在前面的示例发送事件时使用相同的值。它是最好用到所需要的只是限制使用的共享的访问策略的连接字符串。

主机名标识 EventProcessorHost 的实例。在运行时主机群集 (意为多台计算机),建议您提供的名称能够反映正在其运行的机器的身份。

ConsumerGroupName 参数标识此主机表示逻辑的消费群。还有一个默认消费者群体你可以引用使用常量 EventHubConsumer­Group.DefaultGroupName。 你需要进行第一项规定消费群任何其他名称。执行此操作所创建的 Microsoft.ServiceBus.NamespaceManager 的实例,并使用方法,如 CreateConsumerGroupAsync。

最后,您需要提供连接到使用 checkpointConnectionString Azure 存储帐户连接字符串。此存储帐户是主机跟踪有关分区的所有状态事件偏移量。这种状态存储在 blob 以纯文本格式,您可以随时检查。

有其他事件枢纽--预置与集成在一起的 Azure 服务。Azure 流分析 (目前在预览) 提供转换和分析事件流起源于事件中心的声明式类似于 SQL 的语法。同样,事件集线器提供一个壶嘴很受欢迎的 Apache 风暴,现在可在通过 HDInsight Azure 上预览。

总结

这里列出的建筑模式是仅仅是个开始。当执行真实世界的系统,有许多其他问题,您需要考虑的因素。这些问题涉及高级的安全、 资源调配和管理事件生产者、 协议转换、 出站通信。不过,你现在需要构建一个使用事件代理 (例如事件枢纽系统的基本概念与装备。


Christopher Bennage 是微软模式的成员 &实践团队。 他喜欢用电脑制作东西。

感谢以下的微软技术专家对本文的审阅:穆斯塔法 Elhemali 和丹 Rosanova