【问题标题】:Resubmitting dead letter queue message inside a transaction scope在事务范围内重新提交死信队列消息
【发布时间】:2017-12-11 10:48:09
【问题描述】:
鉴于只有一个顶级实体能够参与事务的限制,我如何从死信队列中读取消息并将其放回事务范围内的父队列中?通常我会使用传输队列将消息从一个队列移动到另一个队列作为原子操作,但我不相信 DLQ 有传输队列,即使他们有,我不会有处理传输的问题排队 DLQ!
我需要以安全的方式重新提交,并且在重新提交过程中没有丢失邮件的风险。
【问题讨论】:
标签:
azureservicebus
azure-servicebus-queues
dead-letter
【解决方案1】:
虽然您确实无法重新提交 DLQ 消息,但经过一番调查和反复试验,我发现以下方法效果很好:
- 使用 BrokeredMessage.Clone() 克隆 DLQ 消息
- 从 BrokeredMessage.Properties 中删除 DeadLetterReason 和 DeadLetterErrorDescription 条目
- 在 TransactionScope 内将克隆的消息发送回原始队列并完成 DLQ 消息。
这是一个例子:
using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
// Create new message
var resubmittableMessage = originalMessage.Clone();
// Remove dead letter reason and description
resubmittableMessage.Properties.Remove("DeadLetterReason");
resubmittableMessage.Properties.Remove("DeadLetterErrorDescription");
// Resend cloned DLQ message and complete original DLQ message
await Task.WhenAll(_messageSender.SendAsync(resubmittableMessage), originalMessage.CompleteAsync());
// Complete transaction
scope.Complete();
}
【解决方案2】:
Azure 服务总线不允许重新提交消息。您需要发送带有更正数据的新消息。对于 DLQ 中找到的消息,您可以延迟原始消息,提交副本,如果成功,则按照最初延迟时收到的序列号接收并删除原始 DLQed 消息。
ServiceBus360 使用Deferred DLQ feature 实现了类似的功能。