0

我知道您可以使用 将消息直接发送到队列channel.sendToQueue,这会产生任务和工作人员的情况,其中只有一个消费者将处理每个任务。

我也知道您可以使用channel.publish基于主题的交换,并且消息将根据路由键路由到队列。不过,据我了解,这将始终广播给任何匹配队列上的所有订阅者。

我基本上想使用基于主题的交换,但每个任务只有一个消费者处理。我已经阅读了文档,但我没有看到这样做的方法。

我的用例:

我在多个位置设置了微服务实例。可能有两个在加利福尼亚,三个在伦敦,一个在新加坡,等等。创建任务时,唯一重要的是它由给定位置的一个实例处理。

当然,我可以创建数百个名为“usa-90210”、“uk-ec1a”等的队列。看起来使用主题会更干净。考虑到使用通配符的能力,它也会更加灵活。

如果这不是 RabbitMQ 的功能,我也愿意接受其他想法或想法。

更新

根据 istepaniuk 的建议,我尝试创建两个工作人员,每个工作人员将自己的队列绑定到交换:

const connectionA = await amqplib.connect('amqp://guest:guest@127.0.0.1:5672');
const channelA = await connectionA.createChannel();
channelA.assertExchange('test_exchange', 'topic', { durable: false });
await channelA.assertQueue('test_queue_a', { exclusive: true });
channelA.bindQueue('test_queue_a', 'test_exchange', 'usa.*');
await channelA.consume('test_queue_a', () => { console.log('worker a'); }, { noAck: true });

const connectionB = await amqplib.connect('amqp://guest:guest@127.0.0.1:5672');
const channelB = await connectionB.createChannel();
channelB.assertExchange('test_exchange', 'topic', { durable: false });
await channelB.assertQueue('test_queue_b', { exclusive: true });
channelB.bindQueue('test_queue_b', 'test_exchange', 'usa.*');
await channelB.consume('test_queue_b', () => { console.log('worker b'); }, { noAck: true });

const pubConnection = await amqplib.connect('amqp://guest:guest@127.0.0.1:5672');
const pubChannel = await pubConnection.createChannel();
pubChannel.assertExchange('test_exchange', 'topic', { durable: false });
pubChannel.publish('test_exchange', 'usa.90210', Buffer.from(''));

不幸的是,两个消费者仍在接收消息。

worker a
worker b
4

1 回答 1

1

是的。

我基本上想使用基于主题的交换,但每个任务只有一个消费者处理。我已经阅读了文档,但我没有看到这样做的方法。

使用主题交换并让您的消费者声明并绑定他们自己的队列。你描述的是一个非常常见的场景。教程 5,“主题”中对此进行了概述。

此外,您可以让多个消费者共享一个队列(只是不要声明它exclusive)。这在教程 2, "Workers"中有描述。

消费者的多个实例可以声明相同的队列和绑定,操作是幂等的。使用durable队列(而不是exclusive)还意味着如果您的所有消费者消失或网络出现故障,消息将排队。

于 2021-01-23T18:33:50.863 回答