流量控制用于限制客户端和服务器之间,或服务器和另一台服务器之间的数据流,以防止客户端或服务器被大量数据淹没。

1. 消费者流量控制

这控制了服务器和客户端之间的数据流,因为客户端正在消费消息。出于性能原因,客户端通常会在通过 `receive()` 方法或通过消息监听器异步传递给消费者之前缓冲消息。如果消费者无法像它们被传递和存储在内部缓冲区一样快地处理消息,那么你最终可能会遇到消息不断累积的情况,如果它们不能及时处理,可能会导致客户端内存不足。

1.1. 基于窗口的流量控制

默认情况下,Apache ActiveMQ Artemis 消费者在客户端消费消息之前,会将来自服务器的消息缓冲在客户端缓冲区中。这提高了性能:否则,每次客户端消费一条消息时,Apache ActiveMQ Artemis 都必须去服务器请求下一条消息。然后,这条消息将被发送到客户端,如果有一个可用的话。

对于*每*条消息,都将涉及网络往返,这会大大降低性能。

为了防止这种情况,Apache ActiveMQ Artemis 在每个消费者上预取消息到缓冲区。通过 `consumerWindowSize` 参数确定将缓冲在每个消费者上的消息的总最大大小(以字节为单位)。

默认情况下,`consumerWindowSize` 设置为 1 MiB(1024 * 1024 字节),除非通过 (地址设置) 覆盖。

该值可以是

  • -1 表示*无界*缓冲区

  • 0 表示不缓冲任何消息。

  • >0 表示具有给定最大大小(以字节为单位)的缓冲区。

根据消息传递用例,设置消费者窗口大小可以显着提高性能。例如,让我们考虑两个极端情况

1.1.1. 快速消费者

快速消费者可以像消费消息一样快地处理消息(甚至更快)

为了允许快速消费者,请将 `consumerWindowSize` 设置为 -1。这将允许在客户端进行*无界*消息缓冲。

谨慎使用此设置:如果消费者无法像接收消息一样快地处理消息,则可能会导致客户端内存溢出。

1.1.2. 慢速消费者

慢速消费者需要大量时间来处理每条消息,并且希望防止在客户端缓冲消息,以便它们可以传递给其他消费者。

考虑一个队列中有两个消费者的情况;其中一个非常慢。消息以轮询方式传递给这两个消费者,快速消费者快速处理它所有的消息,直到它的缓冲区为空。此时,仍然有消息在慢速消费者的缓冲区中等待处理,从而阻止它们被快速消费者处理。因此,快速消费者处于空闲状态,而它本可以处理其他消息。

为了允许慢速消费者,请将 URI 上的 `consumerWindowSize` 设置为 0(不进行任何缓冲)。这将阻止慢速消费者在客户端缓冲任何消息。消息将保留在服务器端,准备由其他消费者消费。

将此设置为 0 可以使多个消费者在队列之间进行确定性分布。

大多数消费者不能明确地识别为快速消费者或慢速消费者,而是在两者之间。在这种情况下,将 `consumerWindowSize` 的值设置为优化性能取决于消息传递用例,需要基准测试才能找到最佳值,但在大多数情况下,1MiB 的值是可以的。

请参阅 示例章节,其中有一个示例展示了如何配置 ActiveMQ Artemis 以在处理慢速消费者时防止消费者缓冲。

1.2. 速率限制流量控制

还可以控制消费者可以消费消息的*速率*。这是一种节流形式,可以用于确保消费者不会以快于指定速率的速率消费消息。这使用 `consumerMaxRate` URI 参数进行配置。

速率必须为正整数才能启用此功能,并且是按每秒消息为单位指定的所需最大消息消费速率。将此设置为 `-1` 将禁用速率限制流量控制。默认值为 `-1`。

请参阅 示例章节,了解有关限制消费者速率的工作示例。

速率限制流量控制可以与基于窗口的流量控制一起使用。速率限制流量控制仅影响客户端在一秒钟内可以消费多少条消息,而不影响其缓冲区中的消息数量。因此,如果你有一个较低的速率限制和一个较高的基于窗口的限制,那么客户端的内部缓冲区很快就会被消息填满。

2. 生产者流量控制

Apache ActiveMQ Artemis 还可以限制从客户端发送到服务器的数据量,以防止服务器不堪重负。

2.1. 基于窗口的流量控制

与消费者基于窗口的流量控制类似,Apache ActiveMQ Artemis 生产者默认情况下只能在有足够的信用额度的情况下将消息发送到地址。发送消息所需的信用额度由消息的大小决定。

随着生产者信用额度减少,它们会向服务器请求更多信用额度,当服务器向它们发送更多信用额度时,它们可以发送更多消息。

生产者一次请求的信用额度称为*窗口大小*,它由 `producerWindowSize` URI 参数控制。

因此,窗口大小决定了在需要请求更多之前,可以随时处于飞行中的字节数 - 这可以防止远程连接过载。

2.1.1. 阻塞 CORE 生产者

使用 CORE 协议(由 Artemis Core Client 和 Artemis JMS Client 使用)时,服务器始终会尝试提供与请求的信用额度相同的数量。但是,也可以为任何地址设置最大大小,并且服务器永远不会向任何一个生产者发送超过地址的内存上限所允许的信用额度。虽然单个生产者将获得比可用信用额度(在发布时)更多的信用额度,但理论上,可能有多个生产者与同一地址关联,因此理论上可能在所有生产者中分配的信用额度总量超过了可用信用额度。因此,有可能超出地址限制约

total number of producers on address * producer window size

例如,如果我有一个名为“myqueue”的队列,我可以将最大内存大小设置为 10MiB,并且服务器将控制发送到任何向 myqueue 发送消息的生产者的信用额度数量,以使队列中的总消息永远不会超过 10MiB。

当地址已满时,生产者将在客户端侧阻塞,直到地址释放更多空间,即直到从队列中消费消息,从而释放更多空间以发送更多消息。

我们称之为阻塞生产者流量控制,它是一种有效的方法,可以防止服务器由于生产者发送的消息数量超过其处理能力而导致内存不足。

它是分页的另一种方法,它不会阻塞生产者,而是将消息分页到存储中。

要将地址配置为具有最大大小,并告知服务器,如果该地址已满,则要阻塞该地址的生产者,你需要为该地址定义一个 AddressSettings (通过地址设置配置队列) 块,并指定 `max-size-bytes` 和 `address-full-policy`

地址块适用于注册到该地址的所有队列。即绑定到该地址的所有队列的总内存不会超过 `max-size-bytes`。对于 JMS 主题,这意味着主题中所有订阅的*总*内存不会超过 max-size-bytes。

以下是一个示例

<address-settings>
   <address-setting match="exampleQueue">
      <max-size-bytes>100000</max-size-bytes>
      <address-full-policy>BLOCK</address-full-policy>
   </address-setting>
</address-settings>

上面的示例将队列“exampleQueue”的最大大小设置为 100000 字节,并将阻塞任何向该地址发送消息的生产者,以防止超过最大大小。

请注意,策略必须设置为 `BLOCK` 才能启用阻塞生产者流量控制。

请注意,在默认配置中,所有地址在地址中有 10 MiB 的消息数据后都会设置为阻塞生产者。这意味着你不能向地址发送超过 10MiB 的消息数据,除非它被消费,否则生产者将被阻塞。如果你不希望这种行为,请增加 `max-size-bytes` 参数或更改地址已满消息策略。

生产者信用额度从代理分配给客户端。流量控制信用额度检查(即检查生产者是否拥有足够的信用额度)仅在客户端侧进行。代理可能会过度分配信用额度,就像上面概述的多生产者场景中一样。同样,行为不端的客户端也可能忽略代理发出的流量控制信用额度,并在没有足够的信用额度的情况下继续发送。

2.1.2. 阻塞 AMQP 生产者

Apache ActiveMQ Artemis 开箱即用地支持两种支持流量控制的协议。Artemis CORE 协议和 AMQP。两种协议对流量控制的实现方式略有不同,因此地址已满的 BLOCK 策略对分别使用每种协议的客户端的行为略有不同。

如本章前面所述,CORE 协议使用生产者窗口大小流量控制系统。其中信用额度(代表字节)分配给生产者,如果生产者想发送一条消息,它应该等到它有足够的字节信用额度可用才能发送。AMQP 流量控制信用额度不代表字节,而是代表生产者允许发送的消息数量(无论消息大小如何)。

AMQP 的 BLOCK 机制与上面提到的生产者窗口大小机制的工作原理基本相同。Artemis 会一次性向客户端发放 100 个信用额度,并在客户端信用额度达到 30 时进行刷新。一旦地址已满,代理会停止发放信用额度。但是,由于 AMQP 信用额度代表的是完整的消息而不是字节,因此在某些情况下,如果代理在客户端信用额度耗尽之前继续接受消息,AMQP 客户端可能会显著超过地址的上限。出于这个原因,在地址设置中提供了一个额外的参数,用于指定地址大小的字节上限。一旦达到此上限,Artemis 就会开始拒绝 AMQP 消息。此限制被称为 `max-size-bytes-reject-threshold`,默认设置为 -1(或无限制)。此附加参数允许一种软限制和硬限制,在正常情况下,代理会利用 `max-size-bytes` 参数使用流量控制向客户端施加反向压力,但会通过拒绝消息来保护代理,一旦地址大小达到上限。

2.2. 速率限制流量控制

Apache ActiveMQ Artemis 还允许限制生产者每秒可以发送的消息数量。通过指定这样的速率,Apache ActiveMQ Artemis 会确保生产者永远不会以超过指定速率的速度生产消息。这由 `producerMaxRate` URL 参数控制。

为了启用此功能,`producerMaxRate` 必须是一个正整数,表示以每秒消息数为单位的所需最大消息生产速率。将其设置为 `-1` 将禁用速率限制流量控制。默认值为 `-1`。

请参阅 示例章节,了解限制生产者速率的工作示例。