Azure Service Fabric:如何确定Actor是否已存在

Mar*_*tin 2 azure azure-service-fabric

如何确定具有特定ActorId的Actor是否存在?

ActorProxy仅用于创建Actor。如果提供了一个不存在的ID,而Actor不存在,则会创建一个新的Actor。

标准ActorService可以检索所有Actor,但就我所知,仅此而已。

Eli*_*bel 5

当前没有简单的方法可以做到这一点。Actor旨在抽象出对象实例的生存期。只需在需要时打个电话,它就会在那里。所以我不确定这是否真的必要。

就是说,您可以创建另一种服务方法来遍历服务器端的所有参与者,而不是将整个列表拉到客户端,但是如果您有数百万个参与者实例,那么效率将不高。

或者,您可以在参与者的初始化期间存储标记状态,并查询状态提供者-以增加向参与者增加状态和复制开销为代价。

首先,创建一个服务接口:

public interface IActorServiceEx : IService
{
    Task<bool> ActorExists(ActorId actorId, CancellationToken cancellationToken = default(CancellationToken));
}
Run Code Online (Sandbox Code Playgroud)

然后,创建实现此接口的自定义角色服务:

internal class CustomActorService : ActorService, IActorServiceEx
{
    public CustomActorService(StatefulServiceContext context, ActorTypeInformation actorTypeInfo, Func<ActorBase> actorFactory = null, IActorStateProvider stateProvider = null, ActorServiceSettings settings = null) 
        : base(context, actorTypeInfo, actorFactory, stateProvider, settings)
    {
    }

    public async Task<bool> ActorExists(ActorId actorId, CancellationToken cancellationToken)
    {
        const int batchSize = 1000;
        ContinuationToken token = null;
        do
        {
            var actors = await StateProvider.GetActorsAsync(batchSize, token, cancellationToken);
            if (actors.Items.Contains(actorId))
            {
                return true;
            }
            token = actors.ContinuationToken;
        } while (token != null);
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

或使用标记的替代版本:

internal class Actor1 : Actor, IActor1
{
    protected override async Task OnActivateAsync()
    {
        await StateManager.TryAddStateAsync("Activated", true);
    }
}

internal class CustomActorService : ActorService, IActorServiceEx
{
    ...

    public Task<bool> ActorExists(ActorId actorId, CancellationToken cancellationToken)
    {
        return StateProvider.ContainsStateAsync(actorId, "Activated", cancellationToken);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,在注册演员时使用它,例如:

ActorRuntime.RegisterActorAsync<Actor1>((context, actorType) =>
    new CustomActorService(context, actorType,
    () => new Actor1())).GetAwaiter().GetResult();
Run Code Online (Sandbox Code Playgroud)

并调用此新服务方法:

var actorService = ActorServiceProxy.Create<IActorServiceEx>(serviceUri, actorId);

var exists = await actorService.ActorExists(actorId);
Run Code Online (Sandbox Code Playgroud)