5

我正在创建一个可靠的、有状态的服务参与者。

问题:

有没有办法在actor代理创建期间传递初始化数据(ActorProxy.Create())?基本上相当于我的演员的构造函数。

目前的想法:

我可以通过使用负责初始化状态的参与者方法调用来跟踪代理创建调用来实现这一点。

例如

//Danger, the following calls are not atomic
ITokenManager tokenActor = ActorProxy.Create<IMyActor>(actorId, "AppName");
//Something could happen here and leave my actor in an unknown state
await tokenActor.InitializeAsync(desiredInitialState);

我对这种方法的担忧:

  • 这个操作不是原子的。它可能会使我的演员处于不一致的状态
  • 这种初始化方法现在在 Actor 的整个生命周期中都可用,这是不希望的。
4

3 回答 3

2

在这里给你一些想法。一方面,你需要做初始化的数据真的不能被actor本身使用OnActivateAsync吗?通常,如果我依靠将一些初始数据获取到我的演员的状态,我会这样做。

protected override Task OnActivateAsync()
{
   if (State == null)
   {
       var initialState = await externalSource.GetSomeState();
       // simplified here but map the values properly onto the actual actor state
       this.State = initialState;
       return base.OnActivateAsync();
   }
}

另一个想法是,如果你真的不能让参与者在它自己的激活期间检索数据,那么你很容易创建一个布尔属性,它是参与者状态的一部分,指示你正在谈论的其他激活是否有曾经发生过。

 public Task InitializeAsync(State someState)
 {
     if (State.IsActivated)
     {
         // log out here that someone is attempting to reactivate when they shouldn't
         return Task.CompletedTask;
     }

     State = someState;
     State.IsActivated = true;
     return Task.CompletedTask;
 }

这样,虽然从技术上讲,该方法可以在 Actor 的生命周期内被调用,但您有一个单线程保证,它只会在第一次调用时才真正执行某些操作。

于 2016-02-24T20:36:18.060 回答
1

似乎进行原子初始化的最佳方法是将初始化数据保存在某个外部存储中,并在 OnActivateAsync() 期间使用该存储中的这些数据。

于 2016-02-24T18:54:02.050 回答
0

代理创建不等同于构造函数。在 Service Fabric 中,客户端不应该知道参与者是否已经创建,并且生命周期由运行时管理。

所以actor本身应该初始化为一些默认状态。Actor 实现的工作是在初始化调用之前防止其他调用,并在需要时防止多次初始化。由于演员总是单线程的,因此可以使用布尔标志之类的东西轻松实现。

于 2016-02-23T07:16:58.387 回答