我正在使用RabbitMQ来管理执行持久任务的多个服务器。每个服务器都可以侦听一个或多个队列,但每个服务器一次只能处理一个任务。
每次在服务器中启动使用者时,我都会使用channel.basic_qos(prefetch_count=1)
对其进行配置,以便只为相应的队列处理一个任务。
假设我们有: - 2个队列:task1,task2。 - 2台服务器:server1,server2。 - 两个服务器与task1和task2一起工作。
如果同时生成下一条消息: - tasksA for tasks1 - taskB的messageB - messagesC for tasks1
我的期望: - messageA由server1处理 - messageB由server2处理 。 messageC保持排队,直到其中一个服务器准备就绪(完成当前任务)。
我真正得到的是: - messageA由worker1处理 - messageB由worker2处理 - messageC由worker2处理(错误)
我不会同时启动消费者。实际上,每个服务器中的工作任务都会不断打开/关闭。大多数时间服务器使用不同的队列(server1:tasks1,tasks2,task3; server2:tasks1,tasks5; server3:tasks2,tasks5;等等)。
我怎么能设法做到这一点?
修改 基于Olivier的回答: 任务是不同的。每个服务器都能够处理一些任务,而不是所有任务。服务器一次只能处理一个任务。
我尝试使用与routing_keys的交换,但我发现了两个问题:绑定到路由键task_i的所有服务器都将处理其任务(我需要它只处理一次),如果没有服务器绑定到task_i ,然后删除它的消息(我需要保持排队,直到某个服务器可以处理它)。
答案 0 :(得分:0)
从您提供的说明中看,问题是由于您的服务器同时连接到多个队列。
当您的预取计数设置为1时,连接到3个队列的服务器将消耗最多3条消息,即使他一次只处理一个(根据您的处理描述)。
从您的问题中不清楚是否需要多个队列,或者您是否可以让所有任务最终都在一个队列中:
如果您需要/希望能够"停止"处理某些任务,或控制整个服务器的处理分配,您需要管理服务器中的消费者,一次只有一个活跃的消费者(否则您将阻止/消费一些预取的消息1)。
如果您不需要控制各种任务的处理,那么将所有消息最终放在一个队列中会更加简单,并且单个使用者可以使用每个服务器的预取一个队列设置。