本地随机交换
概述
本地随机交换是 RabbitMQ 4.0 中的一种新的交换类型。它主要用于请求-回复(“RPC”)用例。使用此交换类型,消息始终传递到本地队列,这保证了发布者延迟最小。如果有多个本地队列绑定到交换机,则会随机选择其中一个来将消息传递到该队列。
动机
本地随机交换类型旨在与独占队列一起使用,为请求-回复(“RPC”)工作负载提供更低的延迟组合。
此交换类型的设计假设至少有与集群节点数量一样多的请求-回复消费者。如果不是这样,一些发布的消息将被丢弃。
请求/回复,通常称为 RPC,是一种流行的模式,可以使用像 RabbitMQ 这样的消息代理来实现。一个流行的用例是基于微服务的架构,其中一个服务向另一个服务请求数据。该模式在教程六中介绍。
支持此类场景的关键要求包括
-
低延迟:发布者可能能够继续执行,也可能无法继续执行,直到它收到响应;因此,消息应该尽快传递给消费者。对于其他交换类型,队列可能位于不同的节点上,这意味着需要额外的网络跳跃来传递消息。本地随机交换通过始终将消息传递到本地队列来解决此问题。如果没有本地队列绑定到此交换机,则消息将不会被传递。
-
可扩展性:能够添加额外的应用程序实例来处理更多请求。将更多队列绑定到本地随机交换会自动将请求分散到更多队列。消费者可以使用独占队列来确保它们是节点本地队列。
本地随机交换和独占队列的结合保证了发布和消费过程在消息在集群节点之间传递之前发生。这保证了最小的延迟,并要求在每个集群节点上至少有一个绑定到此类型交换机的本地队列可用。因此,预计(并且需要)应用程序实例的数量,特别是请求/回复(“RPC”)消费者的数量,大于集群中节点的数量。
如何使用本地随机交换
本节将使用基于PerfTest的负载测试来演示此交换类型的行为。
PerfTest 将模拟客户端应用程序。此工作负载**需要**多节点集群。在下面的示例中,我们假设所有节点都在localhost
上运行,并在从 5672 到 5674(含)的三个连续端口上监听。
如果集群不在本地运行或使用不同的端口,则需要调整以下 URI。
假设一个 3 节点集群,以下命令将启动 5 个消费者:第一个节点上启动 2 个,第二个节点上启动 2 个,第三个节点上只启动 1 个
perf-test -H amqp://127.0.0.1:5672 --producers 0 --exchange rpc -t x-local-random --exclusive --routing-key ''
perf-test -H amqp://127.0.0.1:5672 --producers 0 --exchange rpc -t x-local-random --exclusive --routing-key ''
perf-test -H amqp://127.0.0.1:5673 --producers 0 --exchange rpc -t x-local-random --exclusive --routing-key ''
perf-test -H amqp://127.0.0.1:5673 --producers 0 --exchange rpc -t x-local-random --exclusive --routing-key ''
perf-test -H amqp://127.0.0.1:5674 --producers 0 --exchange rpc -t x-local-random --exclusive --routing-key ''
PerfTest 将声明独占队列并将它们绑定到rpc
交换机,交换类型为x-local-random
(交换机本身也将被声明)。本地随机交换不允许在将队列绑定到交换机时使用路由键,这就是为什么上面的--routing-key ''
选项用于覆盖 Perftest 默认值的原因。
路由键在路由消息时会被忽略,而且根本没有路由键,这可以进行一些性能优化。
接下来,必须启动一些生产者。在本例中,我们使用两个生产者,它们具有不同的发布速率
perf-test -H amqp://127.0.0.1:5672 --consumers 0 --exchange rpc -t x-local-random --rate 100
perf-test -H amqp://127.0.0.1:5673 --consumers 0 --exchange rpc -t x-local-random --rate 20
现在,管理界面中的队列选项卡将显示以下内容
正如预期的那样,rabbit-1
(端口 5672)上的队列每秒接收约 50 条消息,rabbit-2
(端口 5673)上的队列每秒接收约 10 条消息,而rabbit-3
(端口 5674)上的消费者没有收到任何消息,因为没有本地发布者。
注意事项和限制
RabbitMQ 前面的负载均衡器将使有效使用此交换类型变得几乎不可能
此交换类型的设计假设集群中的每个节点上都有在线消费者。否则,发布到没有消费者的节点上的消息将被丢弃。
确保这一点的最佳方法是为消费者配置一个特定的节点以连接到该节点。如果该节点不可用,则这些消费者也将(预计不会)可用。
在发布者方面,具有一定灵活性:如果发布者重新连接到另一个节点,它将增加该节点的负载,但消息流和路由仍然应该正常工作。但是,仍然值得考虑为发布者配置一个特定的节点以连接到该节点。就像上面的消费者建议一样,如果该节点不可用,则此类型的发布者也将不可用。
发布时可以使用
mandatory
标志。如果这些消息无法路由,则它们将被返回给发布者。这将允许检测发布者连接到的节点上没有消费者的情况。发布者确认对于 RPC 不是必需的。RabbitMQ 前面的负载均衡器将使有效使用此交换类型变得几乎不可能,因为它很难确保消费者存在于所有节点上并在它们之间均匀分布(这不是必需的,但对于更多事件资源使用而言是最佳的)。因此,强烈建议直接连接到 RabbitMQ 节点。
队列不必在此架构中是独占的,但这可能会简化某些操作。