【问题标题】:Handling transient exceptions when iterating over a Service Fabric ReliableDictionary迭代 Service Fabric ReliableDictionary 时处理瞬时异常
【发布时间】:2017-07-10 07:14:13
【问题描述】:

假设我有一个方法可以遍历 ReliableDictionary 中的所有行,如下所示:

var reliableDictionary = await StateManager.GetOrAddAsync<IReliableDictionary<TKey, TValue>>(dictionaryName);

using (var tx = StateManager.CreateTransaction())
{
    var enumerable = await reliableDictionary.CreateEnumerableAsync(tx);
    var enumerator = enumerable.GetAsyncEnumerator();
    while (await enumerator.MoveNextAsync(cancellationToken))
    {
        // Read enumerator.Current and do something with the value 
        // (not writing back to the dictionary here)
    }
}

如何在此处处理暂时异常的重试(即TimeoutExceptionFabricNotReadableExceptionFabricTransientException)?

枚举器的代码文档不清楚每个方法可以引发哪些异常。哪些方法可以抛出这些瞬态异常 - CreateTransactionCreateEnumerableAsyncGetAsyncEnumeratorMoveNextAsyncenumerator.Current

如果这些方法之一引发了暂时性异常,我应该如何重试?

如果从MoveNextAsyncenumerator.Current 抛出一个瞬态异常,我可以在不中止while 循环的情况下重试它,还是应该创建一个全新的事务并重新从头开始枚举?

【问题讨论】:

  • this文章;它有很多很棒的信息。

标签: c# azure-service-fabric


【解决方案1】:

这篇文章https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-work-with-reliable-collections 描述了在事务下使用可靠集合。基本上你应该做到以下几点:

retry:

try {
   // Create a new Transaction object for this partition
   using (ITransaction tx = base.StateManager.CreateTransaction()) {
      // AddAsync takes key's write lock; if >4 secs, TimeoutException
      await m_dic.AddAsync(tx, key, value, cancellationToken);

      await tx.CommitAsync();
   }
}
catch (TimeoutException) {
   await Task.Delay(100, cancellationToken); goto retry;
}

这里的示例使用 goto 语句,但任何重试处理都应该有效。

如果您知道您的事务将花费更长的时间(就像您的情况一样),您可以修改超时,但您应该考虑它可能对您的解决方案产生的影响。 https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-reliable-collections

所有 Reliable Collection API 的默认超时时间为 4 秒。大多数用户不应覆盖它。

不要使用TimeSpan.MaxValue 进行超时。应该使用超时来检测死锁。

至于您提到的其他异常类型(FabricNotReadableExceptionFabricTransientException),您也可以/应该重试这些异常类型。当您的服务配置发生更改时,Service Fabric 通常会抛出它们,例如主服务器发生更改,或者您由于某种原因最终与辅助服务器通信。 大多数情况它应该是可重试的。 FabricTransientException 只是与 Reliable Services 通信中可能发生的许多异常的基类,它表示如果重试可能会消失的异常。

This answer 描述了FabricNotReadableException,例如,在某些情况下,您需要在客户端重新解析您的服务以结束另一个副本。

【讨论】:

  • 感谢您的回答。我应该在问题中更清楚地说明我真的在寻找关于在枚举可靠字典时抛出异常时该怎么做的指导 - 我应该从头开始再次枚举,还是尝试从当前点继续?您提供的示例建议我应该重试整个事务(即重新从头开始枚举)?
  • 是的,据我所知,重新开始确实是这里唯一的选择。当您尝试启动事务时,可能会发生 TimeOutException,而其他暂时性异常可能是因为您的副本更改了角色或失败(或其他一些更改其角色的操作)。其中任何一个都可能意味着您正在查看或尝试读取的数据不再准确。在大多数情况下,重试整个事务可能是唯一有意义的事情。
猜你喜欢
  • 2017-10-18
  • 2016-09-08
  • 2017-09-18
  • 2016-12-07
  • 1970-01-01
  • 2021-02-15
  • 1970-01-01
  • 1970-01-01
  • 2018-09-24
相关资源
最近更新 更多