Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rabbitmq 员工是否可以基于主题进行消费?_Rabbitmq_Amqp_Node Amqplib - Fatal编程技术网

Rabbitmq 员工是否可以基于主题进行消费?

Rabbitmq 员工是否可以基于主题进行消费?,rabbitmq,amqp,node-amqplib,Rabbitmq,Amqp,Node Amqplib,我知道您可以使用channel.sendToQueue直接将消息发送到队列,这会创建一个任务和工作人员的情况,其中每个任务只有一个使用者处理 我还了解到,您可以通过基于主题的exchange使用channel.publish,邮件将根据路由密钥路由到队列。但据我所知,这将始终向任何匹配队列上的所有订户广播 我基本上希望使用基于主题的exchange,但每个任务只有一个使用者处理。我已经阅读了文档,但我看不出有什么方法可以做到这一点 我的用例: 我在多个位置设置了微服务实例。可能有两个在加利福尼亚

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

我还了解到,您可以通过基于主题的exchange使用
channel.publish
,邮件将根据路由密钥路由到队列。但据我所知,这将始终向任何匹配队列上的所有订户广播

我基本上希望使用基于主题的exchange,但每个任务只有一个使用者处理。我已经阅读了文档,但我看不出有什么方法可以做到这一点

我的用例:

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

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

如果这不是RabbitMQ的特性,我也愿意接受其他想法或想法

更新

根据istepaniuk的建议,我尝试创建了两个worker,每个worker都将自己的队列绑定到exchange:

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
是。

我基本上希望使用基于主题的exchange,但每个任务只有一个使用者处理。我已经阅读了文档,但我看不出有什么方法可以做到这一点

使用主题交换,让消费者声明并绑定他们自己的队列。你所描述的是一个非常常见的场景。这一点在报告中作了概述

此外,您可以让多个使用者共享一个队列(只是不要声明它是独占的)。这在中进行了描述


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

谢谢。我再次浏览了主题页面,但没有看到任何单一消费者的例子。我尝试将一个单独的队列绑定到每个使用者,但两个使用者仍然被触发。请检查我上面的代码。@DaiBu为什么这两个消费者没有收到这个消息?两者都在
usa.*
上绑定,因此在测试消息
usa.90210
右侧都匹配。我想是沟通失误。要明确的是,我有一些任务需要由给定位置的下一个可用工作人员(池外)处理。我基本上想说,“下一个在美国比佛利山庄免费的消费者,请处理这项任务。”主题交换需要使用一个独特的主题挑出特定的工作人员,对吗?我需要能够发布到一个工作人员池中,并且只有一个人负责执行任务。这仍然符合你的建议吗?@DaiBu好的,你走的路是对的。如果不将队列声明为“独占”并启动多个使用者(共享同一队列),则消息将分布在它们之间,共享负载。只要删除“独占”并启动许多“worker A”消费者,就会创建您想要的这样一个“池”。声明(而不是断言!)每次交换、队列和绑定都很好,这是一个幂等操作。不管是断言还是声明,这似乎是API之间的变化,但都是一样的。