Azure 服务总线 上的限流操作

云原生解决方案提供可以随工作负荷一起缩放的无限制资源的概念。 虽然这种概念在云中比本地系统更真实,但云中仍然存在一些限制。 如本文所述,这些限制可能会导致标准层和高级层中的客户端应用程序请求 受到限制

标准层中的限流

服务总线 的标准层采用多租户模式,并使用标准预付费套餐定价模型。 同一群集中的多个命名空间共享分配的资源。 对于开发人员环境、QA 环境和低吞吐量生产系统,建议选择标准层。

过去,服务总线 采用的是严格取决于资源利用率的粗粒度限制措施。 但是,有机会优化限制逻辑,并为共享这些资源的所有命名空间提供可预测的限制行为。

为确保在所有使用相同资源的 服务总线 标准命名空间之间公平地使用和分配资源,服务总线 标准当前采用基于信用点的限制机制。

注释

需要注意的是,限流对于 Azure 服务总线 或任何云原生服务来说都不是什么新鲜事

基于额度的限流本质上只是优化多租户标准层环境中各个命名空间共享资源的方式,从而使所有共享这些资源的命名空间都能公平地使用资源。

什么是基于信用点的限流?

基于额度的限制会限制在特定时间段内可对给定命名空间执行的操作次数。 以下是基于额度的限流工作流程。

  • 在每个时间段开始时,服务总线为每个命名空间提供一些额度。
  • 发送方或接收方客户端应用程序执行的任何操作将计入这些额度(并从可用额度中减去)。
  • 如果额度耗尽,后续操作将受到限制,直到下一个时间段的开始。
  • 信用额度在下一个时间段开始时进行补充。

什么是额度限制?

额度限制目前设置为 每秒 1000 个额度 (每个命名空间)。 并非所有操作都一样。 下面是每个操作的信用成本。

操作 信用成本
数据操作(Send、、SendAsyncReceiveReceiveAsyncPeek 每条消息 1 个信用额度
管理操作(对队列、主题、订阅和筛选器执行 CreateReadUpdateDelete 操作) 10 个积分

注释

发送到主题时,每条消息在可供订阅接收之前,都会根据筛选器进行评估。 每个筛选器评估还计入信用额度(即每个筛选器评估 1 个信用额度)。

我怎么知道自己是否被限流了?

当客户端应用程序请求受到限制时,客户端应用程序会收到以下服务器响应。

The request was terminated because the entity is being throttled. Error code: 50009. Please wait 2 seconds and try again.

如何避免被限流?

对于共享这些资源的各个 服务总线 命名空间,必须实施某种形式的公平使用策略。 限制机制可确保某个工作负载的突发峰值不会导致共享同一资源的其他工作负载也被限制。 如本文后面所述,由于客户端软件开发工具包(SDK)和其他Azure PaaS 产品/服务内置了默认重试策略,因此没有受到限制的风险。 任何被限流的请求都会通过指数退避策略进行重试,并在额度补充后最终成功处理。

可以理解,某些应用程序可能对被限流较为敏感。 在这种情况下,建议将当前服务总线标准命名空间迁移到高级命名空间。 迁移后,您可以为 服务总线 命名空间分配专用资源,并在工作负载激增时适当纵向扩展这些资源,从而降低受到限制的可能性。 此外,当工作负荷减少到正常级别时,可以缩减分配给命名空间的资源。

高级层中的限流

服务总线高级层根据消息传送单元将专用资源分配给客户设置的每个命名空间。 这些专用资源提供可预测的吞吐量和延迟,建议用于高吞吐量或敏感的生产级系统。 此外,高级层还允许客户在遇到工作负荷峰值时纵向扩展其吞吐量容量。 有关详细信息,请参阅 Azure 服务总线命名空间的自动更新消息传送单元

服务总线 Premium 中的限制机制如何工作?

对于高级层级,采用独占资源分配时,限流仅取决于分配给该命名空间的资源限制。 如果请求数超过当前资源可以服务的数量,则请求会受到限制。

我怎么知道自己是否被限流了?

有多种方法可用于识别 服务总线 高级层中的限流情况。

  • 受限制的请求显示在Azure Monitor 请求指标中,用于确定有多少请求受到限制。
  • CPU 使用率高表示当前资源分配较高,如果当前工作负荷未减少,请求可能会受到限制。
  • 内存使用率 表示当前资源分配较高,如果当前工作负荷未减少,请求可能会受到限制。

如何避免被限流?

由于 服务总线 高级命名空间已具有专用资源,因此当工作负载出现峰值或预期将出现峰值时,可以通过增加分配给该命名空间的消息传送单元数量来降低被限流的可能性。 有关详细信息,请参阅 Azure 服务总线命名空间的自动更新消息传送单元

当并发接收请求超过限制时进行限流

除了前文所述的基于资源和基于信用额度的节流机制之外,服务总线 还会限制单个实体上的并发接收请求数量。 队列、主题或订阅最多允许 5,000 个并发接收请求。 对于某个主题,此限制适用于其所有订阅中的并发接收操作总数。 当实体上进行中的接收请求数超过此限制时,系统会以“服务器繁忙”错误拒绝额外的接收请求,直到未完成的请求数降至该限制以下。

当应用程序在同一实体上打开大量接收方(AMQP 接收链接),同时保持其活动状态时,通常会发生这种情况。 每个已打开的接收器都会向服务授予信用,并持续轮询消息,即使实体为空时也是如此。 当并发接收方足够多时,接收请求总量会超过限制,该实体就会开始返回“服务器繁忙”错误。

服务总线 SDK 使用内置的重试策略来处理服务器繁忙响应,该策略使用指数退避,以便重试不会添加进一步的负载。 若要避免首先达到此限制,请遵循以下建议:

  • 将单个实体上的并发接收器数量保持在远低于上限的水平。 每个消费者实例配备几个接收器通常就足以实现高吞吐量。 在同一实体上打开数千个接收器是一种反模式,这会增加被限制的可能性,却无法提高吞吐量。
  • 关闭不再需要的接收器,而不要让闲置的接收器保持开启并持续轮询。
  • 如果您确实需要非常大量的并发消费者,可以跨多个实体进行横向扩展,例如将工作负载分区到多个队列或订阅中。

FAQs

节流会如何影响我的应用程序?

当请求受到限制时,它意味着服务正忙,因为它面临的请求超过了资源允许的请求数。 如果稍后再次尝试相同的操作,待服务处理完当前工作负载后,该请求即可得到处理。

由于限流是任何云原生服务的预期行为,因此,服务总线 SDK 本身内置了重试逻辑。 默认设置为采用指数退避策略进行自动重试,以确保同一请求不会每次都被限流。 默认重试逻辑适用于每个操作。

注释

调用其他第三方服务的消息处理代码也可能受到其他服务的限制。 有关如何处理这些方案的详细信息,请参阅 有关限制模式的文档

限流会导致数据丢失吗?

Azure 服务总线针对持久性进行优化。 在服务确认请求成功之前,请确保发送到服务总线的所有数据都提交到存储。

服务总线成功确认请求后,表示服务总线已成功处理请求。 如果服务总线返回失败,则意味着服务总线无法处理请求,客户端应用程序必须重试请求。

但是,当请求受到限制时,服务意味着它现在无法接受并处理请求,因为资源限制。 这并不意味着任何数据丢失,因为服务总线只是没有查看请求。 在这种情况下,依赖于 服务总线 SDK 的默认重试策略可确保最终处理请求。

有关使用服务总线消息传送的详细信息和示例,请参阅以下高级主题: