Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.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
什么';这是放弃Azure SB消息的正确方法,以便它在将来以我可以控制的方式再次可见?_Azure_Servicebus_Azureservicebus_Azure Servicebus Queues - Fatal编程技术网

什么';这是放弃Azure SB消息的正确方法,以便它在将来以我可以控制的方式再次可见?

什么';这是放弃Azure SB消息的正确方法,以便它在将来以我可以控制的方式再次可见?,azure,servicebus,azureservicebus,azure-servicebus-queues,Azure,Servicebus,Azureservicebus,Azure Servicebus Queues,所以这个场景是,我使用一个SB队列来限制对其他服务的传出回调。回拨其他服务的标准问题之一是,它们可能会停机一段无法控制的时间。假设我检测到目标已关闭/没有响应,那么放弃该消息以使其不会立即重新出现在队列中的最佳模式是什么 以下是我知道、尝试过或正在考虑的一些方法: 显然,如果我只使用BrokeredMessage::放弃(),消息将被解锁并放回队列。对于这种情况和我试图避免的情况,这显然是不可取的 如果我忽略了一个事实,即我遇到了一个错误,并且从不调用放弃,这将阻止它立即出现,但我实际上无法精

所以这个场景是,我使用一个SB队列来限制对其他服务的传出回调。回拨其他服务的标准问题之一是,它们可能会停机一段无法控制的时间。假设我检测到目标已关闭/没有响应,那么放弃该消息以使其不会立即重新出现在队列中的最佳模式是什么

以下是我知道、尝试过或正在考虑的一些方法:

  • 显然,如果我只使用
    BrokeredMessage::放弃()
    ,消息将被解锁并放回队列。对于这种情况和我试图避免的情况,这显然是不可取的

  • 如果我忽略了一个事实,即我遇到了一个错误,并且从不调用放弃,这将阻止它立即出现,但我实际上无法精确控制它再次出现的时间,我希望实现一个衰减重试策略

  • 我想也许我可以调用
    BrokeredMessage::放弃(IDictionary)
    并以某种方式更新
    scheduledQueueTimeUTC
    属性,但我已经尝试过了,除了消息的初始发送之外,似乎没有办法影响该属性。有道理,但值得一试

  • 我考虑过在这种情况下只使用
    BrokeredMessage::Complete()
    ,实际上只使用
    ScheduledEqueueTimeUTC
    属性集将消息的新副本排入队列


最后一颗子弹似乎太重了,但鉴于排队的固有性质,我得出结论,这可能是正确的答案。我只是想在Azure SB队列中可能有一种更好的方法来实现这一点,而我却错过了这种方法。

如果我是你,我会从互联网上的众多页面中寻找解决方案。基本上,您希望进行重试,如果重试失败,则会将消息连续发送到死信队列。我们可以在以后重新查询这些消息。这可以是手动的,也可以是自动的,具体取决于需求

请注意,虽然我发送给您的页面与camel相关,因此该页面上描述的所有内容都适用于.NET和azure。如果您对上面的bullet#2感兴趣,这里有一个更为.NET的例子:在调用
Receive(timespan)
时,您不能在消息上设置TTL timespan,而不是默认的
Receive()
?然后,您可以简单地放弃消息(无需调用
放弃()
),当TTL过期时,消息应该重新出现在队列中。虽然这并没有给你说“x秒后重新出现”的细粒度控制,但它确实给了你消息重新出现的可预测性


注意:对于基于存储的队列,您可以更新不可见性超时,以便对消息重新显示进行精细控制。

如果您想暂时保存消息,并且有地方写下SequenceNumber(在会话队列中可能处于会话状态),您可以将其延迟()。延迟消息可以使用一个特殊的接收重载来检索,该重载给出SequenceNumber;这也是唯一的办法,让他们再次除了他们到期,所以小心。此功能是为工作流和状态机构建的,以便它们能够处理无序的消息到达。

感觉有点粗糙,但我提出的解决方案是

try 
{
   ...
}
catch (Exception ex)
{
   await Task.Delay(30000);
   throw;
}
这样,它将等待30秒,然后让它放弃。在配置的次数之后,它最终会死信

我正在使用Azure Webjobs进行接收。
虽然我使用的是
Task.Delay
而不是
Thread.Sleep
,但它似乎并没有在等待时释放线程来处理队列中的另一个项目(默认情况下,Webjobs并行处理16个).

我更喜欢最后一种方法,因为它似乎是使用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()

大卫,谢谢你的建议。问题是,我们希望使用智能的、衰减的重试。所以,举个简单的例子,如果这是第一个错误,我可能只想从现在开始把它放回队列30秒。第二个1米,第三个5米,第四个30米,第五个1小时,等等。要做到这一点,我们需要知道它以前被接收了多少次,我们可以通过DeliveryCount(或其他自定义道具)来跟踪,但是如果我们还没有执行Receive(),我们就没有属性数据来告诉为.Alistair设置TTL的时间,谢谢您的建议。我一定会查看链接的。我们希望在这种情况下避免单独排队/单独处理。在经过一定数量的处理尝试后,我们最终会对消息进行死信处理,我们只是在寻找一种更简单的方法来分散重试次数,直到达到最大值。最后,我认为使用新的ScheduledQueueTimeUTC值重新对消息进行排队可能会为我们在SB案例中购买我们想要的东西,我只是希望在API中有一种更干净的方法来实现这一点,而不是重新发送消息。好的,那么,告诉我这听起来是否正确:我们可以延迟()主队列上的原始消息,并在辅助队列上放置一条“重试”消息(可能使用ScheduledQueueTimeUTC)它有原始邮件的SequenceNumber,我可以通过特殊的Receive()重载返回并获取。我很困惑,第二个队列添加了什么,而这不是通过您的“高压”解决方案来完成的,即按计划的传递时间复制邮件。我看到的唯一问题是交付计数总是重置为1,因此它不是确定指数退避计算输入的好来源