放弃Azure SB消息以使其在将来以我可以控制的方式再次可见的正确方法是什么?

ffdz8vbo  于 2022-12-14  发布在  其他
关注(0)|答案(6)|浏览(146)

因此,我使用SB队列来限制对其他服务的传出回调。回调其他服务的一个标准问题是,它们可能会在无法控制的时间内关闭。假设我检测到目标关闭/没有响应,那么放弃该消息以使其不会立即重新出现在队列中的最佳模式是什么?
以下是我知道、尝试过或正在考虑的一些方法:

  • 显然,如果我只使用BrokeredMessage::Abandon(),消息将被解锁并放回队列中。这显然是不希望的,因为这是我试图避免的。
  • 如果我只是忽略我遇到错误的事实,并且从不调用Abandon,这将使它不会立即显示,但我真的无法细粒度控制它在多长时间内再次显示,我希望实现一个衰减重试策略。
  • 我想也许我可以调用BrokeredMessage::Abandon(IDictionary<string, object>)并以某种方式更新ScheduledEnqueueTimeUTC属性,但我已经尝试过了,似乎除了最初发送消息之外,没有一种方法可以影响该属性。这有意义,但值得一试。
  • 在这种情况下,我考虑只使用BrokeredMessage::Complete(),实际上只是使用ScheduledEqueueTimeUTC属性集将消息的新 * 副本 * 入队。

最后一个要点似乎太难了,但我得出的结论是,考虑到队列的固有性质,这可能是正确的答案。我只是想,在Azure SB队列中可能有一种更好的方法来完成这一点,我错过了。

zkure5ic

zkure5ic1#

如果你想把一条消息暂时放一放,并且你有地方写下SequenceNumber(它可能在会话队列的Session状态中),你可以使用Defer()方法。这也是除了它们过期之外再次访问它们的唯一方法,所以要小心。这个特性是为工作流和状态机构建的,这样它们就可以处理无序的消息到达。

rqdpfwrv

rqdpfwrv2#

在上述第2项中:当调用Receive(TimeSpan)而不是默认的Receive()时,您不能只在消息上设置TTL时间跨度吗?然后,您可以简单地放弃该消息(不调用Abandon()),并且当TTL过期时,消息应该重新出现在队列中。“它确实可以给予你预测消息何时再次出现。”
注意:使用基于存储的队列,您可以更新不可见性超时,以便 * 将 * 为您提供对消息重新出现的细粒度控制。

q1qsirdb

q1qsirdb3#

感觉有点古怪,但我想到的解决办法是

try 
{
   ...
}
catch (Exception ex)
{
   await Task.Delay(30000);
   throw;
}

这样,它将等待30秒钟,然后才允许它放弃。它最终将死信后,配置的次数。
我正在使用Azure Webjobs进行接收。虽然我使用的是Task.Delay而不是Thread.Sleep,但它似乎没有释放线程来处理队列中等待的另一个项目(默认情况下,Webjobs并行处理16个项目)。

lmyy7pcs

lmyy7pcs4#

如果我是你,我会参考互联网上的Enterprise integration patterns页面中的一个来寻找解决方案。基本上,你想进行一次重试,如果失败,就将消息连续发送到一个死信队列。这些消息可以在以后重新排队。这可以根据需要手动或自动进行。
请注意,虽然我发送给你的页面与camel相关,因此该页面上描述的所有Java都适用于.NET和azure。如果你感兴趣,这里有一个更.NET的http://www.eaipatterns.com/

wwtsj6pe

wwtsj6pe5#

我更喜欢最后一种方法,因为它似乎是使用Azure服务总线的内置特性的最简单的解决方案。
流程如下:

var newMessage = new BrokeredMessage();
// Copy message body and properties from original message...

var scheduleTimeUtc = DateTimeOffset.UtcNow.Add(...);
await queueClient.ScheduleMessageAsync(newMessage, scheduleTimeUtc);

await originalMessage.CompleteAsync()
bfrts1fy

bfrts1fy6#

消息重新排队解决方案有一个问题(尽管这似乎是目前为止最好的解决方案)。这在主题/多订阅者模型中不会有效地工作,因为即使其他订阅者成功处理了新消息,它们也会将新消息传递给这些订阅者。
为了跟踪原始消息ID和正确的传递计数,可以在新消息中使用Message.UserProperties

相关问题