我们在Service-Fabric上的状态服务中使用以下方法。该服务有分区。有时我们从代码的安静中获得FabricNotReadableException。
public async Task HandleEvent(EventHandlerMessage message)
{
var queue = await StateManager.GetOrAddAsync<IReliableQueue<EventHandlerMessage>>(EventHandlerServiceConstants.EventHandlerQueueName);
using(ITransaction tx = StateManager.CreateTransaction())
{
await queue.EnqueueAsync(tx, message);
await tx.CommitAsync();
}
}
这是否意味着分区已关闭并正在移动?我们打了一个二级分区?因为在某些情况下还会引发FabricNotPrimaryException。
我看过MSDN链接(https://msdn.microsoft.com/en-us/library/azure/system.fabric.fabricnotreadableexception.aspx)。但是
是什么表示当分区无法接受读取时引发的异常。
意思?分区无法接受读取的情况发生了什么?
答案 0 :(得分:13)
在幕后,Service Fabric有几种状态可以影响给定副本是否可以安全地提供读写操作。他们是:
FabricNotReadableException映射到其他状态(您实际上不需要担心或区分它们),并且可能在各种情况下发生。一个示例是,如果您尝试执行读取的副本是“备用”副本(副本已关闭且已恢复,但副本集中已有足够的活动副本)。另一个例子是副本是主节点但是正在关闭(例如由于升级或因为它报告了故障),或者它当前正在进行重新配置(例如,正在添加另一个副本)。由于某些安全检查和Service Fabric需要在引擎盖下处理的原子更改,所有这些条件都将导致副本无法满足写入的少量时间。
您可以将FabricNotReadableException视为可重复。如果您看到它,只需再次尝试呼叫,最终它将解析为NotPrimary或Granted。如果你得到FabricNotPrimary异常,通常这应该被抛回到客户端(或以某种方式通知客户端),它需要重新解析才能找到当前的主服务器(Service Fabric发布的默认通信堆栈)注意不可重复的异常并代表您重新解决。
FabricNotReadableException目前存在两个已知问题。
答案 1 :(得分:1)
发布作为回答(对于asnider的评论 - 3月16日17:42)因为评论太长了! :)
我也陷入了这个问题22.我的svc启动并立即收到消息。我想在OpenAsync中封装服务启动并设置一些ReliableDictionary值,然后开始接收消息。但是,此时Fabric不可读,我需要拆分这个&#34; startup&#34;在OpenAsync和RunAsync之间:(
我的服务中的 RunAsync
和我的客户端中的OpenAsync
似乎也有不同的取消令牌,所以我还需要解决如何处理这个问题。它只是感觉有点凌乱。关于如何在我的代码中整理这个问题,我有很多想法,但是有没有人想出一个优雅的解决方案?
如果ICommunicationClient有一个RunAsync接口,当Fabric变得准备/可读时被取消并且当Fabric关闭副本时被取消,那将是很好的 - 这将严重简化我的生活。 :)
答案 2 :(得分:0)
我遇到了同样的问题。我的监听器在服务的主线程之前启动。我将需要启动的侦听器列表排队,然后在主线程中尽早激活了所有侦听器。结果,可以处理所有传入的消息并将其放入适当的可靠存储中。我的简单解决方案(这是服务总线侦听器):
| t.NAME | t1.REPORTINGTYPE | t1.REPORTINGPERIOD |
|----------------|------------------|--------------------|
| Mr John Smith | Final | Mar 2017 |
| Ms Janet Smith | Draft | Jun 2018 |
======================
在主线程中,调用该函数以启动侦听器操作:
public Task<string> OpenAsync (CancellationToken cancellationToken)
{
string uri;
Start ();
uri = "<your endpoint here>";
return Task.FromResult (uri);
}
public static object lockOperations = new object ();
public static bool operationsStarted = false;
public static List<ClientAuthorizationBusCommunicationListener> pendingStarts = new List<ClientAuthorizationBusCommunicationListener> ();
public static void StartOperations ()
{
lock (lockOperations)
{
if (!operationsStarted)
{
foreach (ClientAuthorizationBusCommunicationListener listener in pendingStarts)
{
listener.DoStart ();
}
operationsStarted = true;
}
}
}
private static void QueueStart (ClientAuthorizationBusCommunicationListener listener)
{
lock (lockOperations)
{
if (operationsStarted)
{
listener.DoStart ();
}
else
{
pendingStarts.Add (listener);
}
}
}
private void Start ()
{
QueueStart (this);
}
private void DoStart ()
{
ServiceBus.WatchStatusChanges (HandleStatusMessage,
this.clientId,
out this.subscription);
}
...
此问题很可能在此处出现,因为所讨论的总线已经具有消息,并在创建侦听器的第二秒开始触发。尝试访问状态管理器中的任何内容都会引发您所询问的异常。