wcf - 在没有 WCF 的 MSMQ 中创建重试机制

标签 wcf msmq message-queue messaging

我有多个现有应用程序通过 System.Messaging API 使用 MSMQ 发送和接收消息。队列通常是非事务性的,是 MSMQ 3 和 4 的混合。

接收应用程序现在处理有害消息,以至于在第一次出现任何异常时,消息被放入错误队列以进行人工干预。但事实证明,绝大多数手动干预只是简单地将消息移回主队列以进行另一次尝试,此时它会成功。因此,为了使该过程自动化,我想向接收器添加一个重试功能,以便将消息移回主队列给定的次数,每次之间有给定的延迟。

我不想重新发明轮子,而是想利用 MSMQ 开箱即用的任何东西以及任何流行的或最佳实践模式。为此,有很多关于 MSMQ 4 中对有害消息的额外支持。但它们似乎无法通过 .Net 轻松访问。此外,我可以找到使用它们的唯一引用是通过带有 MSMQ 绑定(bind)的 WCF。

如果不使用 WCF,任何人都可以提出任何模式或指向任何实现重试的示例吗?

最佳答案

我找不到一个单一的、流行的模式来做到这一点。但是在 System.Messaging 中探索了一下之后,我能够利用 Message 属性和 MSMQ 行为,我认为这是用最少的移动部件完成工作的合适方式。

这是我实现的。结果证明它相当简单和轻量级 - 代码不多且易于维护:

我创建了一个名为 RetryLevel 的对象,它具有三个属性:

整数顺序,
整数重试次数,
时间跨度延迟

接收应用程序的配置现在有一个 RetryLevel 列表。所以新特性基本支持n级重试。

然后我创建了一个名为 RetryInfo 的对象。这个对象有两个属性:

int尝试,
字符串源队列路径

RetryInfo 对象的一个​​实例被序列化并存储在每个最终被重试的 Message 的 Extension 属性中。这使我能够跟踪消息本身的当前重试状态,从而消除了维护单独的重试元数据存储的需要以及协调消息 Id、保持数据同步等的所有开销。

最后,我在接收器的配置中添加了一个等待队列路径。此队列是消息在“超时”时将被丢弃的地方。

因此,现在,当消息处理程序拒绝一条消息时,接收方将反序列化它的 RetryInfo,如果有的话,并查看(先前)尝试的数量以确定它已达到哪个配置的 RetryLevels。

然后接收者将消息的 TimeToBeRecieved (TTBR) 属性设置为 DateTime.Now 加上相应 RetryLevel 的延迟值。然后它将 AdministrativeQueue 属性设置为从 RetryInfo 的 SourceQueuePath 属性创建的队列,并将 Message 的 AcknowledgeType 设置为 AcknowledgeTypes.NegativeReceive。最后,它将消息放入等待队列。

从这里,MSMQ 监视消息的 TTBR。当超时时,MSMQ 将消息放回其管理队列属性中的队列中,该属性是消息最初来自的队列。如果消息继续被处理程序拒绝,它只会向上移动到 RetryLevels。

如果消息的尝试次数超过配置的 RetryLevels 上的所有 NumberOfRetries,则消息的 TTBR 属性设置为 TimeSpan.Zero,UseDeadLetterQueue 属性设置为 true,并且消息像任何其他重试一样被放入等待队列。然而,这一次,它立即超时,MSMQ 将它发送到等待队列的主机的系统死信队列 (DLQ),在那里可以手动处理它。

关于wcf - 在没有 WCF 的 MSMQ 中创建重试机制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15115089/

相关文章:

java - 消息驱动 Bean - 单总线、多激活规范

multithreading - Silverlight - 一次将应用程序限制为一个 WCF 调用

c# - 无法运行 WCF https Web 服务

c# - 如何使用WCF和MSMQ在C#中实现单发布者和多订阅者异步消息系统?

windows-8.1 - MSMQ HTTP 禁用错误

c++ - 为什么必须将 SetWindowsHookEx 与 Windows 消息队列一起使用

wcf - 在WCF服务中HttpContext.Current是否不应该为null?

.net - 如何在 C#.NET 中执行类似 Heroku 的延迟作业?

.net - 不使用 MSMQ 的 NServiceBus 的替代方案

java - JMS 中的批处理/批量处理