如何将数据传递给`OnActivateAsync()`来初始化我的有状态演员?

时间:2016-02-22 21:38:34

标签: c# azure-service-fabric service-fabric-actor

我正在创建一个可靠的,有状态的服务角色。

问题:

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

当前的想法:

我可以通过使用负责初始化状态的actor方法调用来跟进代理创建调用来实现此目的。

E.g。

//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);

我对这种方法的关注:

  • 此操作不是原子操作。这可能会让我的演员处于不一致的状态
  • 此初始化方法现在可在演员的整个生命周期内使用,这是不受欢迎的。

3 个答案:

答案 0 :(得分:2)

这里有几个想法。首先,在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();
   }
}

另一个想法是,如果你真的不能让actor在它自己的激活过程中检索数据,你很容易创建一个布尔属性,它是actor状态的一部分,指示你是否或其他激活谈论的事情一直在发生。

 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的生命周期中调用,但你有一个单独的线程保证,它只会在第一次调用它时才真正做某事。

答案 1 :(得分:1)

使用原子初始化的最佳方法似乎是将初始化数据保存在某个外部存储中,而在OnActivateAsync()期间,会从该存储中使用此数据。

答案 2 :(得分:0)

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

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