迭代Service Fabric ReliableDictionary时处理瞬态异常

时间:2017-02-20 21:06:58

标签: c# azure-service-fabric

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

1 个答案:

答案 0 :(得分:2)

本文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

  

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

  

请勿使用TimeSpan.MaxValue超时。应该使用超时来检测死锁。

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

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