RabbitMQ + MassTransit:如何从处理中取消排队的消息?

时间:2018-08-14 21:27:55

标签: rabbitmq nservicebus masstransit message-bus

在某些特殊情况下,我需要以某种方式告诉接收方消费者一些消息不应被处理。否则,两个系统将不同步(我们将处理一些过时的外部系统,例如,如果删除了连接,则必须丢弃该连接范围内的所有排队的操作)。

冒险并手动解决问题消息?赔偿措施(在我的案子中可能很难支持)?还有吗?

3 个答案:

答案 0 :(得分:1)

有几种方法:

  • 您可以设置发送消息的时间:await endpoint.Send(myMessage, c => c.TimeToLive = TimeSpan.FromHours(1));,但这将适用于以这种方式发送(或发布)的所有消息。在考虑您的要求之后,我会考虑这一点。这是技术性的,但这是一种适当的消息传递模式。

  • 使消息本身具有TTL和生成时间戳属性,并让使用者确定消息是否仍然值得处理。这是更多的业务,而且可能是最正确的方法。

  • 组合技术和业务-将时间戳和TTL保留在消息标题中,以免污染您的消息合同,并使用自定义中间件将其过滤掉。在这种情况下,您需要小心记录此类丢弃,这样您就不会奇怪为什么消息会不时消失。

  • 几乎所有不可靠的集成都可以使用sagas进行监视,并带有超时信息。例如,我们使用传奇与Twilio集成。由于我们无法为其打开网络挂钩,因此我们将在一段时间后进行轮询以检查消息状态。收到消息时可以启动一个传奇,并安排一条消息以检查处理是否仍在等待。如评论中所述,您可以使用“所需的人工干预”方式来解决问题,也可以让传奇决定放弃该消息。

  • 一种类似的方法是使用查找表,在该表中放置与处理无关的消息列表。这样的表将类似于sagas的列表。似乎这种方式还需要调度。无论是在这里还是在传奇方面,我都建议对DropIt消息使用单独的接收终结点(队列),并且只使用一个使用者。这样可以防止DropIt消息滞留在等待处理的集成消息后面(有些消息应该已经丢弃)

  • 使用RMQ管理API从队列中删除消息。这是最糟糕的方法,我不推荐使用。

答案 1 :(得分:0)

据我了解,您正在构建一个向第三方系统发送消息的系统。换句话说,您无法控制的系统。它具有API,但并非总是可以执行补偿操作,因为API不提供补偿功能,还是因为操作是在第三方系统内执行的,无法补偿或回滚?

如果可能,尝试通过sagas解决此问题。确保传奇以正确的顺序执行不同的步骤(发送消息)。这样无法补偿的消息将最后发送。如果失败,可以补偿的这种方式的消息将由传奇来补偿。无法补偿的补偿应在您确定不必补偿时,最后发送。因为最后一条消息是同步所有系统的最后一步。

总而言之,这是分布式系统的问题之一,它使所有内容保持同步。补偿措施是处理此问题的方法。如果无法采取补偿措施,那么您将处于非常困难的境地。尝试看看企业是否可以通过变得更加灵活并接受您需要补偿的东西来帮助您,他们会告诉您这是不可能的。

答案 2 :(得分:0)

  

在某些特殊情况下,我需要以某种方式告诉接收方消费者一些消息不应被处理。

您不能将其还原为:

告诉消费者可以处理较早的消息。

这样,您可以轻松地在作用于两条消息的状态机(如传奇)中打开它。如果第二条消息从未到达,则可以在一段时间后丢弃第一条消息或执行其他操作。

此处的策略是暂停/等待,直到确定无需还原任何动作为止。