【发布时间】:2016-11-25 05:48:28
【问题描述】:
在应用程序的负载测试期间(使用动态负载报告服务),整个应用程序停止工作,因为有状态分区的一个副本发出警告。
Warning System.RAP IStatefulServiceReplica.ChangeRole(S)Duration Thu, 21 Jul 2016 3:36:03 GMT Infinity 131135817636324745 false false Start Time (UTC): 2016-07-21 13:35:43.632
这发生在副本的负载平衡之后,这发生在分区的第 4 个副本上,尽管我们只针对 3。所以即使 SF 只是杀死它,应用程序也应该没问题(因为主节点和其他 2 个辅助节点都已启动)。然而,整个事情都卡住了。 (从日志中我可以看到至少 10k 事件仍需要处理,但整个事情都停止了)
在上面的图片中,您可以看到特定副本的详细信息。此副本与其他辅助副本的唯一区别在于以下值:
- 读取状态
- 写入状态
- 当前服务操作
- 队列内存大小(在复制队列中)
- 第一个序列号(在复制队列中)
- 上次接收复制操作的时间 Utc
- 上次接收复制操作的时间 Utc
- 上次确认发送时间 Utc
我还觉得奇怪的是副本状态显示:已准备好,不再重新配置。正如读/写状态所说,它仍在重新配置 我正在运行最新的 SDK(2.1.163,2016 年 7 月 18 日发布)。我认为错误修复就在那里,但即使重现变得更加困难,它仍然会发生。有谁知道这可能是什么原因或如何解决这个问题?
编辑:调试结果,基于 Vaclav (22-7-2016) 的回答
在 Vaclav 做出响应后,我开始在 RunAsync 中记录所有内容,以确定实际导致问题的原因。那么如果请求取消,代码的哪一部分没有退出。正如 Vaclav 指出的那样,当请求取消时,该方法并没有停止。但是,似乎卡住的代码部分是本机 Service Fabric。
using(ITransaction tx = StateManager.CreateTransaction())
{
await queue.TryDequeueAsync(tx, _queueTimeout, cancellationToken);
await tx.CommitAsync();
}
队列是 ReliableQueue,超时设置为默认 4 秒,cancelationtoken 来自 RunAsync。在每行之间添加日志记录后,我们得到了以下日志记录模式
//pre transaction
using(ITransaction tx = StateManager.CreateTransaction())
{
//pre dequeue
await queue.TryDequeueAsync(tx, _queueTimeout, cancellationToken);
//dequeued
await tx.CommitAsync();
//committed
}
//post transaction
在每一行我都记录了取消请求的值,当取消请求被触发时,后台任务会记录下来。结果我们得到了例如:
pre transaction: False
predequeue: False
dequeued: False
CancelationTokenFired: True
确切位置可能会有所不同,但 CancelationTokenFired 之前的最后一个日志始终是
- 交易前
- 提前出队
- 出队
如前所述,这是在最新的 SDK (18-7-2016) 上完成的,据称该 SDK 对类似问题进行了错误修复。该问题也出现在较旧的 SDK 上,并且在当时更为频繁。但即使在新版本上,每次运行仍可重现。
【问题讨论】:
-
我不会将取消令牌用于任何可靠的收集操作。尝试不更改超时或添加取消令牌。
-
@Nick 这就是我们之前所拥有的,但这也不起作用。无论如何,你怎么称呼它也无关紧要:)
-
这是在适当的集群上还是在本地开发集群上?我可能会在我的 localhost 开发集群上看到类似的东西。
-
@NickRandell 这是在本地开发集群上。
-
有趣 - 我想知道这个区域是否仍然存在错误,尤其是在本地集群上。自 163 更新以来,我的 azure 集群似乎一直运行良好,但我在本地集群上仍然存在这些问题。我还在 MSDN 服务结构论坛上问过一个关于此的问题。 social.msdn.microsoft.com/Forums/en-US/…