2016-08-03 104 views
7

我们遇到了ITransaction.CommitAsync的一些奇怪行为。有时对CommitAsync的调用需要24小时才能完成。什么能导致ITransaction.CommitAsync调用花费很长时间(24h)?

在我们的场景中,我们每5分钟从硬件设备读取电表数据并将检查点存储在可靠的字典中。因此,每5分钟左右,运行以下代码:

var profileCheckpoints = await StateManager.GetOrAddAsync<IReliableDictionary<string, DateTime>>(StateNameProfileCheckpoints); 

using (var tx = StateManager.CreateTransaction()) 
{ 
    // Dictionary key is a device guid + device register id, 
    // e.g.: 13cdaad8-9b8b-4fba-b336-e72e06c047ab-1.0.99.1.0.255 
    var key = GetCheckpointKey(context); 

    // checkpoint is a DateTime 
    await profileCheckpoints.SetAsync(tx, key, checkpoint); 

    // this call will sometimes take 24h to complete 
    await tx.CommitAsync(); 
} 

我们已经在有状态的服务中运行了多个后台任务。每个后台任务都与单个硬件设备通信并运行上述代码。所有任务都使用相同的可靠字典,但只更新特定于设备的密钥。

某些任务运行良好,CommitAsync调用很快返回。对于其他任务,CommitAsync呼叫可能突然需要24小时才能完成。没有例外,代码继续照常。一旦发生这种情况,除非我们重新启动服务,否则为此任务执行的所有其他CommitAsync调用也需要24小时才能完成。

集群和所有应用程序在门户网站中都被报告为健康的。然而,当我在事件查看器看一下不同的节点上我看到被记录以下警告(每5秒一次左右):

dropping message <some guid>, Actor = Transport, Action = ‘’, fault = FABRIC_E_CONNECTION_CLOSED_BY_REMOTE_END 

任何想法,可能是这个原因吗?

+0

已经过了大概一年,所以这种方法应该已经运行了大约365次;) 你有没有深究过这一点?根据你的发现分享什么? – ckittel

+0

不幸的是,我们有点放弃了这种情况,现在将这些检查点存储在Blob存储中。将尝试找一些时间来重新测试。 –

回答

0

GetCheckpointKey与设备通信吗?难道这是占用线程和阻塞,这意味着线程池已经耗尽。

可能抓着吸管,但GetCheckpointKey上没有等待,这让我有点怀疑。

+0

所有与设备的通信都是在上面的代码被点击的时候完成的。 GetCheckpointKey只包含一个string.Format调用来连接两个字符串以获取字典密钥。下一次调用(SetAsync)仍然正常运行,并且很快完成。 CommitAsync调用然后挂起。 –