Service Fabric,确定是不是存在特定参与者
Posted
技术标签:
【中文标题】Service Fabric,确定是不是存在特定参与者【英文标题】:Service Fabric, determine if specific actor existsService Fabric,确定是否存在特定参与者 【发布时间】:2019-04-04 09:37:23 【问题描述】:我们正在使用 Azure Service Fabric,并使用参与者对特定设备进行建模,使用设备的 ID 作为ActorId
。当我们请求一个给定 id 的参与者(如果它尚未实例化)时,Service Fabric 将实例化一个新的参与者实例,但我似乎找不到允许我查询特定设备 ID 是否已经具有实例化参与者的 api。
我了解在获取时间点真相时可能存在一些分布式/时间问题,但出于我们的特定目的,我们不需要硬实时答案,但可以满足于最佳猜测。理论上,我们只想联系当前主节点以获取由ActorId
解析的特定分区,并返回设备是否具有实例化的参与者。
理想情况下,这是一个快速/高性能的调用,基本上比例如更快。实例化 actor 并调用一个方法来了解它是否已正确初始化并且不仅仅是一个“空”actor。
您可以使用ActorServiceProxy
来遍历特定分区的信息,但这似乎不是一种获取信息的高效方式。
有对此有见解的人吗?
【问题讨论】:
目前没有办法做到这一点。一种解决方法可能是让参与者将其 ID 存储在 azure table、有状态服务或其他存储中,并调用该存储以获取此信息。您无需激活已停用的演员即可以这种方式存在。 【参考方案1】:您可以检查先前是否已在任何服务分区中激活actor的唯一官方方法是使用ActorServiceProxy
查询,如here所述:
IActorService actorServiceProxy = ActorServiceProxy.Create(
new Uri("fabric:/MyApp/MyService"), partitionKey);
ContinuationToken continuationToken = null;
do
PagedResult<ActorInformation> page = await actorServiceProxy.GetActorsAsync(continuationToken, cancellationToken);
var actor = page.Items.FirstOrDefault(x => x.ActorId == idToFind);
continuationToken = page.ContinuationToken;
while (continuationToken != null);
根据 SF Actors 的性质,它们是虚拟的,这意味着它们始终存在,即使您之前没有激活,因此执行此检查会有点困难。
正如您所说,查询所有参与者并不高效,因此,您可以尝试的其他解决方法是:
将 ID 存储在其他地方的可靠字典中,每次激活 Actor 时,您都会引发一个事件并将 ActorID 插入到字典中(如果还没有的话)。
您可以使用OnActivateAsync()
actor 事件来通知它的创建,或者
您可以使用 ActorService 中的自定义 Actor 工厂来注册 Actor 激活
您可以将字典存储在另一个参与者或另一个 StatefulService 中
在actor中创建一个属性,该属性由actor激活时自己设置。
OnActivateAsync()
检查这个属性之前是否设置过
如果尚未设置,则设置一个新值并将其存储在一个变量(非持久值)中,以表明该演员是新的
每当您与演员互动时,您都会设置此项以表明它不再是新的
下一次激活,属性已经设置好了,应该不会发生任何事情。
创建一个自定义 IActorStateProvider 来执行选项 2 中提到的相同操作,而不是在 actor 中处理它,而是在它下面处理一个级别。老实说,我认为这有点工作,只有当你必须对许多演员类型做同样的事情时才会很方便,选项 1 和 2 会更容易。
按照 Peter Bons 的建议进行操作,将 ActorID 存储在 ActorService 之外,就像在数据库中一样,如果您必须从集群外部进行检查,我只会建议使用此选项.
.
如果您想在演员之外管理这些事件,以下片段可以帮助您。
private static void Main()
try
ActorRuntime.RegisterActorAsync<NetCoreActorService>(
(context, actorType) => new ActorService(context, actorType,
new Func<ActorService, ActorId, ActorBase>((actorService, actorId) =>
RegisterActor(actorId);//The custom method to register the actor if new
return (ActorBase)Activator.CreateInstance(actorType.ImplementationType, actorService, actorId);
)
)).GetAwaiter().GetResult();
Thread.Sleep(Timeout.Infinite);
catch (Exception e)
ActorEventSource.Current.ActorHostInitializationFailed(e.ToString());
throw;
private static void RegisterActor(ActorId actorId)
//Here you will put the logic to register elsewhere the actor creation
【讨论】:
接受这个作为答案,因为它概述了使某些事情起作用的可能方法。【参考方案2】:或者,您可以创建一个有状态的DeviceActorStatusActor
,它会在创建后立即由DeviceActor
通知(调用)。 (共享 ActorId 以进行关联。)
根据您的需要,您还可以使用同一个状态跟踪演员注册多个演员。
您将获得出色的性能和近乎实时的信息。
【讨论】:
以上是关于Service Fabric,确定是不是存在特定参与者的主要内容,如果未能解决你的问题,请参考以下文章
如何确定运行 Service Fabric 集群的操作系统类型
如何使用 VMScaleSet 将 NodeTypes 添加到 ServiceFabric,并将特定配置(例如使用数据磁盘)添加到现有 Service Fabric 群集?