3

我最近一直在阅读消息系统,并专门研究了RabbitMQNServiceBus。据我了解,如果一条消息由于某种原因失败,它会立即再次尝试多次。然后,两个系统都提供了稍后重试的可能性,例如 5 秒后重试。当五秒钟过去后,消息会再次发送多次。

我引用了 Vaughn Vernon 在实现领域驱动设计(p.502) 中的话:

处理此问题的另一种方法是简单地重试发送直到它成功,可能使用 Capped Exponential Back-off。在 RabbitMQ 的情况下,重试可能会失败很长一段时间。因此,结合使用消息 NAK 和重试可能是最好的方法。尽管如此,如果我们的进程每五分钟重试三次,这可能就是我们所需要的。

对于 NServiceBus,这称为二级重试,当重试发生时,会发生多次。

为什么它需要发生多次?为什么它不是每五分钟重试一次?五分钟后第一次重试失败和第二次重试(可能只是几毫秒后)成功的机会是多少?

如果由于某些配置不需要它(是吗?),为什么我发现的所有示例都有多次重试?

4

2 回答 2

5

我的背景是 NServiceBus,所以我的答案可能是用这些术语表达的。

第一级重试非常适合非常短暂的错误。死锁就是一个很好的例子。您尝试更改数据库,并且您的事务被选为死锁牺牲品。在这些情况下,第一级重试是完美的。大多数时候,您只需要一次一级重试。如果数据库中有很多争用,也许 2 或 3 次重试就足够了。

二级重试是为了减少暂时性错误。想想 Web 服务关闭 10 秒,或者故障转移集群中的 SQL Server 数据库切换,这可能需要 30-60 秒。如果您在几毫秒后重试,这对您没有任何好处,但在 10、20、30 秒后,您可能会有好机会。

但是,问题的关键是在 5 次第一级重试后延迟,为什么要再试 5 次,然后再延迟?

首先,在您的第一次二级重试时,您仍然可能会遇到死锁或其他非常短暂的错误。毕竟,目标通常不是使系统尽可能慢,因此如果问题确实是暂时的,则最好不必在重试之前等待额外的延迟。当然,基础设施无法知道问题的短暂性。

第二个原因是,如果它们都相同,则更容易配置。X 级重试和 Y 级每级尝试 = X*Y 总尝试,配置文件中只有 2 个数字。在 NServiceBus 中,是这 2 个值加上回退时间跨度,因此配置如下所示:

<SecondLevelRetriesConfigEnabled="true" TimeIncrease ="00:00:10" NumberOfRetries="3" />
<TransportConfig MaxRetries="3" />

这很简单。尝试 3 次。等待 10 秒。尝试 3 次。等待 20 秒。尝试 3 次。等待 30 秒。尝试 3 次。然后你就完成了,你进入一个错误队列。

为每个级别配置不同的值将需要更复杂的配置故事。

于 2013-06-21T13:53:08.690 回答
3

存在一级重试以弥补网络和数据库锁定等快速问题。这在 NSB 中是可配置的,因此如果您不想要它们,可以将它们关闭。二级重试是为了补偿更长的中断。例如,我们使用 SLR 来补偿每晚同时回收的数据库。

OOTB 功能增加了 SLR 之间的持续时间,因为它假定如果它在上一次不起作用,您将需要更多时间来修复它。存在可覆盖的重试策略,因此您可以更改 SLR 的工作方式。

在 NSB 中,FLR 总是先出现,而 SLR 不会发挥作用,除非在 FLR 之后事务仍然失败。此外,您可以完全禁用 SLR 并构建您自己的具有附加功能的自定义故障管理器。我们有一个流程,我们有一个故障管理器,可以将问题发送到配备人员的帮助台,因为这是解决特定问题子集的唯一方法。

于 2013-06-21T13:51:15.997 回答