Service Fabric 可靠队列 FabricNotReadableException
Service Fabric Reliable Queues FabricNotReadableException
我有一个包含 1000 个分区和 1 个副本的有状态服务。
RunAsync 方法中的此服务有一个无限循环,我在其中调用可靠队列来获取消息。
如果没有消息,我等待 5 秒,然后重试。
我曾经成功地使用 Azure 存储队列来做到这一点。
但是对于 Service Fabric,我收到了数千个 FabricNotReadableExceptions,服务变得不稳定,我无法更新或删除它,我需要取消整个簇。
我尝试更新它,但在 18 小时后它仍然卡住,所以我正在做的事情出现了严重的错误。
这是方法代码:
public async Task<QueueObject> DeQueueAsync(string queueName)
{
var q = await StateManager.GetOrAddAsync<IReliableQueue<string>>(queueName);
using (var tx = StateManager.CreateTransaction())
{
try
{
var dequeued = await q.TryDequeueAsync(tx);
if (dequeued.HasValue)
{
await tx.CommitAsync();
var result = dequeued.Value;
return JSON.Deserialize<QueueObject>(result);
}
else
{
return null;
}
}
catch (Exception e)
{
ServiceEventSource.Current.ServiceMessage(this, $"!!ERROR!!: {e.Message} - Partition: {Partition.PartitionInfo.Id}");
return null;
}
}}
这是 RunAsync
protected override async Task RunAsync(CancellationToken cancellationToken)
{
while (true)
{
var message = await DeQueueAsync("MyQueue");
if (message != null)
{
//process, takes around 500ms
}
else
{
Thread.Sleep(5000);
}
}
}
我还用 Task.Delay 更改了 Thread.Sleep(5000),并且出现了数千个 "A task was canceled" 错误。
我在这里缺少什么?
是不是周期太快了,顺丰不能及时更新其他副本?
我应该删除所有副本只留下一个吗?
我应该改用新的 ConcurrentQueue 吗?
我在生产和本地有 50 或 1000 个分区的问题,没关系。
我很困惑。
谢谢
您需要遵守传递给 RunAsync
实施的 cancellationToken
。当 Service Fabric 出于任何原因(包括升级)想要停止您的服务时,它会取消令牌,并且在取消令牌后它将无限期地等待 RunAsync
到 return。这可以解释为什么您无法升级您的应用程序。
我建议在你的循环中检查 cancellationToken.IsCancelled
,如果它被取消了就退出。
FabricNotReadableException
的发生可能有多种原因 - 的答案有全面的解释,但要点是
You can consider FabricNotReadableException retriable. If you see it, just try the call again and eventually it will resolve into either NotPrimary or Granted.
我有一个包含 1000 个分区和 1 个副本的有状态服务。
RunAsync 方法中的此服务有一个无限循环,我在其中调用可靠队列来获取消息。 如果没有消息,我等待 5 秒,然后重试。 我曾经成功地使用 Azure 存储队列来做到这一点。
但是对于 Service Fabric,我收到了数千个 FabricNotReadableExceptions,服务变得不稳定,我无法更新或删除它,我需要取消整个簇。 我尝试更新它,但在 18 小时后它仍然卡住,所以我正在做的事情出现了严重的错误。
这是方法代码:
public async Task<QueueObject> DeQueueAsync(string queueName)
{
var q = await StateManager.GetOrAddAsync<IReliableQueue<string>>(queueName);
using (var tx = StateManager.CreateTransaction())
{
try
{
var dequeued = await q.TryDequeueAsync(tx);
if (dequeued.HasValue)
{
await tx.CommitAsync();
var result = dequeued.Value;
return JSON.Deserialize<QueueObject>(result);
}
else
{
return null;
}
}
catch (Exception e)
{
ServiceEventSource.Current.ServiceMessage(this, $"!!ERROR!!: {e.Message} - Partition: {Partition.PartitionInfo.Id}");
return null;
}
}}
这是 RunAsync
protected override async Task RunAsync(CancellationToken cancellationToken)
{
while (true)
{
var message = await DeQueueAsync("MyQueue");
if (message != null)
{
//process, takes around 500ms
}
else
{
Thread.Sleep(5000);
}
}
}
我还用 Task.Delay 更改了 Thread.Sleep(5000),并且出现了数千个 "A task was canceled" 错误。
我在这里缺少什么? 是不是周期太快了,顺丰不能及时更新其他副本? 我应该删除所有副本只留下一个吗?
我应该改用新的 ConcurrentQueue 吗?
我在生产和本地有 50 或 1000 个分区的问题,没关系。
我很困惑。 谢谢
您需要遵守传递给 RunAsync
实施的 cancellationToken
。当 Service Fabric 出于任何原因(包括升级)想要停止您的服务时,它会取消令牌,并且在取消令牌后它将无限期地等待 RunAsync
到 return。这可以解释为什么您无法升级您的应用程序。
我建议在你的循环中检查 cancellationToken.IsCancelled
,如果它被取消了就退出。
FabricNotReadableException
的发生可能有多种原因 -
You can consider FabricNotReadableException retriable. If you see it, just try the call again and eventually it will resolve into either NotPrimary or Granted.