如何在RabbitMQ中收回邮件?

时间:2010-09-21 08:38:19

标签: message-queue rabbitmq amqp cancellation

我在RabbitMQ上有一个类似于作业队列的东西,并且在请求取消作业时,我想撤回尚未开始处理的任务(他们的消息未被确认),对应于从已被路由到的队列中收回这些消息。

我没有在AMQP或RabbitMQ API中找到此功能;也许我的搜索不够好?或者我是否必须使用解决方法(这不难,但仍然)?

4 个答案:

答案 0 :(得分:8)

我会通过让工作人员检查某种权威数据源来确定作业是否应该继续来解决这个问题。例如,工作人员将检查作业在数据库中的状态,以查看作业是否已被取消。

对于处理作业的速度可能比授权存储可以更新和读取的速度更快的情况,为其他特征换取速度的保证较少的数据存储可能是有用的。

这方面的一个例子是使用Redis作为取消处理消息的存储而不是像MySQL这样的关系数据库。 Redis非常快,但对它所拥有的数据提供的保证较少,而MySQL速度要慢得多,但对它所拥有的数据提供了更多的保证。

最后,使用其他来源检查是否处理消息的概念是相同的,但实现方式取决于您的特定情况。

答案 1 :(得分:4)

RabbitMQ不允许您在邮件排队后修改或删除邮件。为此,您需要某种数据库来保存每个作业的状态,并使用RabbitMQ通知感兴趣的各方该状态的变化。

对于低容量,您可以将其与每个作业的队列一起使用。创建队列,将作业描述发布到队列,向工作人员公布队列名称。如果在处理作业之前需要取消作业,则删除作业的队列;当工人们来取得工作描述时,他们会发现队列已经消失了。

轻量级,通常更好的是使用redis或其他键/值存储来保存作业状态(删除或缺少记录意味着已取消或不存在的作业)并使用rabbitmq通知新的/已删除/已更改的记录在键/值存储区中。

答案 2 :(得分:2)

至少有两种实现目标的方法:

答案 3 :(得分:1)

您需要订阅已路由消息的所有队列,并使用ack消费它们。

例如,如果您使用“test”作为路由密钥发布到主题交换,并且有3个订阅“test”的持久队列,则需要使用这三个队列。最好添加另一个消费者进程也会监听的队列,并告诉他们忽略这些消息。

另一种选择,因为你使用RabbitMQ,就是编写一个自定义交换插件,它将接受一些带外指令来清除所有队列。例如,您可能让该交换读取一个特殊的消息头,告诉它清除此消息所指向的所有队列。这确实需要编写Erlang代码,但实现了4种不同的交换类型,因此您只需要复制最相似的交换类型并为新的bahaviours编写代码。如果您只为此使用自定义标头,则消息正文可以是消费者的正常消息。

总结一下:

1)发布者需要自己使用消息 2)发布者可以在特殊队列中发送特殊消息,告诉消费者忽略该消息 3)发布者可以向自定义交换发送特殊消息,该消息将在向消费者发送此特殊消息之前清除队列中的任何现有消息。