假设我有一个方法迭代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)
}
}
我如何在此处理暂时异常的重试(即TimeoutException
,FabricNotReadableException
和FabricTransientException
)?
枚举器的代码文档不清楚可以在每个方法上抛出哪些异常。哪些方法可以抛出这些瞬态异常 - CreateTransaction
,CreateEnumerableAsync
,GetAsyncEnumerator
,MoveNextAsync
和enumerator.Current
?
如果从这些方法之一抛出瞬态异常,我该如何重试?
如果从MoveNextAsync
或enumerator.Current
抛出一个瞬态异常,我可以在不中止while循环的情况下重试它,还是应该创建一个全新的事务并从头再次开始枚举?
答案 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
超时。应该使用超时来检测死锁。
至于您提到的其他异常类型(FabricNotReadableException
和FabricTransientException
),您可以/应该重试这些异常类型。当服务配置发生变化时,Service Fabric会抛出它们,例如主服务器的更改或者由于某种原因最终与辅助服务器进行通信。 大多数情况它应该是可重试的。 FabricTransientException
只是与可靠服务进行通信时可能发生的许多异常的基类,它表示如果重试可以消失的异常。
This answer描述了FabricNotReadableException
,例如,在某些情况下,您需要在客户端重新解析您的服务,以便在另一个副本上结束。