我们在Service Fabric中有一个有状态的服务,包括RunAsync方法和几个服务调用。
一个服务调用允许在ReliableQueue
中排队using(ITransaction tx = StateManager.CreateTransaction())
{
await queue.EnqueueAsync(tx, message);
queueLength = await queue.GetCountAsync(tx);
await tx.CommitAsync();
}
另一方面,RunAsync尝试出列事件:
using(ITransaction tx = StateManager.CreateTransaction())
{
await queue.TryDequeueAsync(tx);
queueLength = await queue.GetCountAsync(tx);
await tx.CommitAsync();
}
GetCountAsync似乎会导致死锁,因为这两个事务会相互阻塞。如果我们切换顺序会有所帮助:首先计算,然后是出队/入队?
答案 0 :(得分:1)
在两个不同的地方进行两次交易不应该导致死锁,因为它们就像互斥锁一样。导致他们的是在交易中创建交易。
也许那就是发生了什么?我最近养成了创建交易事务的命名函数的习惯,即DoSomethingTransactionalAsync,如果它是私人助手,我通常会创建两个版本,其中一个采用tx,一个采用tx创建。
例如:
AddToProcessingQueueAsync(ITransaction tx, int num)
和AddToProcessingQueueTransactionalAsync(int num)
。
答案 1 :(得分:1)
这可能是由于ReliableQueue今天是严格的FIFO并且一次只允许一个读写器。您可能没有看到死锁,您看到超时(如果不是这样,请纠正我)。除了:
之外,没有真正的方法可以防止超时重新排序事情不应该导致任何变化。