迭代 Service Fabric ReliableDictionary 时处理暂时性异常

Handling transient exceptions when iterating over a Service Fabric ReliableDictionary

假设我有一个方法可以遍历 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 循环的情况下重试它,还是应该创建一个全新的事务并重新从头开始枚举?

这篇文章 https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-work-with-reliable-collections 描述了在事务下使用 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

The default time-out is 4 seconds for all the Reliable Collection APIs. Most users should not override this.

Do not use TimeSpan.MaxValue for time-outs. Time-outs should be used to detect deadlocks.

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

描述了 FabricNotReadableException,例如,在某些情况下,您需要 re-resolve 客户端中的服务才能在另一个副本上结束。