Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
分区负载均衡是一种Azure 事件中心技术,用于在应用程序的多个实例之间分配事件处理工作负荷。 事件处理程序客户端自动管理分区所有权,并协调所有活动使用者实例之间的工作分布。
在较新的 SDK 版本(5.0 及更高版本中),EventProcessorClient(.NET 和 Java) 或 EventHubConsumerClient (Python 和 JavaScript) 会自动处理负载均衡。 通过注册事件处理程序来订阅感兴趣的事件。
本文介绍使用多个客户端应用程序实例从事件中心读取事件的示例方案。 它还介绍了分区所有权、检查点和负载均衡等关键概念。
小窍门
如果使用旧版客户端库,请参阅迁移指南:.NET、Java、Python 和 JavaScript。
注意
事件中心实现扩展的关键在于分区消费者这一理念。 与竞争消费者模式相比,分区消费者模式能够通过消除争用瓶颈并促进端到端并行处理,实现高扩展性。
示例方案
作为示例方案,假设有一个家庭保安公司需要监控 100,000 个家庭。 该公司每隔一分钟就要从每个家庭中安装的各种传感器(例如运动检测器、门/窗打开传感器、玻璃破碎检测器等)获取数据。 该公司为居民提供一个网站,让他们近乎实时地监控家庭中的活动。
每个传感器将数据推送到事件中心。 在事件中心配置了 16 个分区。 在消费端,需要有一种机制来读取这些事件,并对其进行汇总(筛选、聚合等),再将汇总结果转储到 Blob 存储中,然后将其呈现到一个对用户友好的网页上。
使用者应用程序
在分布式环境中设计使用者时,方案必须处理以下要求:
- 缩放: 创建多个使用者,每个使用者获取若干事件中心分区的读取所有权。
- 负载均衡: 动态增加或减少使用者。 例如,将新的传感器类型(例如一氧化碳检测器)添加到每个家庭后,事件数会增多。 在这种情况下,操作员(人类)会增加使用者实例的数目。 然后,消费者组可以重新平衡各自拥有的分区,以便与新加入的消费者分担负载。
- 故障时无缝恢复: 如果某个使用者(使用者 A)发生故障(例如,托管使用者的虚拟机突然崩溃),其他使用者能够拾取使用者 A 拥有的分区并继续。 此外,称作“检查点”或“偏移量”的延续点应该位于使用者 A 发生故障时的确切位置,或者略微在该位置的前面。
- 消费事件:尽管前面三个要点涉及消费者端的管理,但还必须有用于消费事件并对其进行有意义处理的代码。 例如,将其聚合并上传到 Blob 存储。
事件处理器或使用者客户端
无需生成自己的解决方案即可满足这些要求。 Azure 事件中心 SDK 提供此功能。 在.NET或Java SDK 中,使用事件处理程序客户端(EventProcessorClient)。 在 Python 和 JavaScript SDK 中,使用 EventHubConsumerClient。 在旧版 SDK 中,事件处理程序主机(EventProcessorHost)支持这些功能。
对于大多数生产方案,请使用事件处理程序客户端读取和处理事件。 处理器客户端以高性能和容错的方式处理事件集线器的所有分区事件,同时提供检查其进度的方法,从而提供稳健的使用体验。 在给定事件中心的使用者组上下文中,事件处理器客户端能够以协作方式工作。 客户端会在实例变得可用或不可用时自动管理工作分配和负载均衡。
分区所有权
事件处理器实例通常拥有并处理来自一个或多个分区的事件。 系统在与事件中心和使用者组组合关联的所有活动事件处理程序实例之间均匀分配分区的所有权。
每个事件处理程序都有唯一标识符,并通过在检查点存储中添加或更新条目来声明分区的所有权。 所有事件处理程序实例定期与此存储通信,以更新其自己的处理状态并了解其他活动实例。 系统使用此数据平衡活动处理器之间的负载。 新实例可以加入处理池以进行纵向扩展。 当实例由于故障或缩减规模而关闭时,系统会平稳地将分区所有权转移到其他活动处理器。
检查点存储中的分区所有权记录会跟踪事件中心命名空间、事件中心名称、使用者组、事件处理器标识符(也称为所有者)、分区 ID 和上次修改时间。
| 事件中心命名空间 | 事件中心名称 | 使用者组 | 所有者 | 分区标识符 | 上次修改时间 |
|---|---|---|---|---|---|
| mynamespace.servicebus.chinacloudapi.cn | myeventhub | 我的消费者小组 | 3be3f9d3-9d9e-4c50-9491-85ece8334ff6 | 0 | 2020-01-15T01:22:15 |
| mynamespace.servicebus.chinacloudapi.cn | myeventhub | 我的消费者小组 | f5cc5176-ce96-4bb4-bbaa-a0e3a9054ecf | 1 | 2020-01-15T01:22:17 |
| mynamespace.servicebus.chinacloudapi.cn | myeventhub | 我的消费者小组 | 72b980e9-2efc-4ca7-ab1b-ffd7bece8472 | 2 | 2020-01-15T01:22:10 |
| : | |||||
| : | |||||
| mynamespace.servicebus.chinacloudapi.cn | myeventhub | 我的消费者小组 | 844bd8fb-1f3a-4580-984d-6324f9e208af | 15 | 2020-01-15T01:22:00 |
每个事件处理器实例获取分区的所有权,并从上一个已知的检查点开始处理分区。 如果处理器发生故障(VM 关闭),则其他实例通过查看上次修改时间来检测失败。 其他实例尝试获取以前由非活动实例拥有的分区的所有权。 检查点存储保证只有一个实例能够成功声明分区所有权。 因此,在任何给定的时间点,最多有一个处理器从分区接收事件。
接收消息
创建事件处理程序时,请指定处理事件和错误的函数。 每次调用处理事件的函数都会从特定的分区传送单个事件。 必须处理此事件。 如果要确保使用者至少处理一条消息一次,请使用重试逻辑编写自己的代码。 但请注意有害消息。
处理事件的速度相对较快。 也就是说,尽量减少处理量。 如果需要写入存储并执行某种路由,最好是使用两个使用者组和两个事件处理器。
检查点
检查点记录是指事件处理器在分区内标记或提交最后一个成功处理的事件位置的过程。 标记检查点通常发生在处理事件并在使用者组中按分区发生的函数中。
如果事件处理器与分区断开连接,则另一个实例可以在之前提交的该使用者组中该分区的最后一个处理器的检查点处恢复处理分区。 当处理器建立连接时,它会将此偏移量传递给事件中心,以指定要从其开始读取数据的位置。 这样,你便可以使用检查点将事件标记为已由下游应用程序“完成”,并在事件处理器出现故障时提供复原能力。 可以通过指定这个检查点过程的较低偏移量来返回较早的数据。
当检查点将事件标记为已处理时,它会使用事件的偏移量和序列号添加或更新检查点存储中的条目。 确定更新检查点的频率。 每次成功处理事件之后进行更新可能会影响性能和成本,因为这会对底层检查点存储触发写入操作。 另外,对每个单独事件都进行检查点记录,这表明其属于队列式消息传递模式,而在这种情况下,服务总线 队列可能比事件中心更合适。 Event Hubs 的理念是,在大规模场景下实现“至少一次”传递保障。 将下游系统指定为幂等,即可方便地在发生故障或重启(导致多次收到相同的事件)后恢复。
使用 Azure Blob 存储作为检查点存储时,请遵循以下建议:
- 对每个使用者组使用单独的容器。 可以使用同一存储帐户,但每个组使用一个容器。
- 不要将存储帐户用于任何其他用途。
- 不要将容器用于任何其他用途。
- 在部署的应用程序所在的同一区域中创建存储帐户。 如果应用程序位于本地,请尝试选择最近的区域。
在 Azure 门户的“存储帐户”页上的“Blob 服务”部分,确保禁用以下设置。
- 分层命名空间
- Blob 软删除
- 版本控制
线程安全性和处理程序实例
默认情况下,将会针对给定分区按顺序调用处理事件的函数。 来自同一分区的后续事件以及对该函数的调用会在后台排队等待处理,而事件泵则继续在其他线程上运行。 可以并发处理来自不同分区的事件。 必须同步跨分区访问的任何共享状态。
相关内容
请参阅以下快速入门: