grain的生命周期
概述
Orleans grain使用可观察的生命周期(参见Orleans Lifecycle)进行有顺序的激活和反激活。这允许在grain激活和收集期间,按顺序启动和停止grain的逻辑,系统组件和应用程序的逻辑。
生命周期的阶段
预定义的grain生命周期的阶段如下。
public static class GrainLifecycleStage
{
public const int First = int.MinValue;
public const int SetupState = 1000;
public const int Activate = 2000;
public const int Last = int.MaxValue;
}
First
- grain生命周期的第一阶段SetupState
- 在激活前设置grain状态。对于有状态的grain,这是从存储中装载状态的阶段。Activate
- 在此阶段调用OnActivateAsync
和OnDeactivateAsync
Last
- grain生命周期的最后阶段
虽然在grain的激活期间,使用了grain的生命周期,但由于在某些错误情况下(例如silo崩溃),grain并非总是能被反激活,因此应用程序不应指望在grain的反激活期间,能始终执行grain的生命周期。
参与grain的生命周期
应用程序逻辑可以通过两种方式参与grain的生命周期:grain可以参与其生命周期,和/或组件可以通过grain的激活的上下文访问生命周期(请参阅IGrainActivationContext.ObservableLifecycle)。
grain总是参与自己的生命周期,因此可以通过覆盖参与方法,来导入应用程序逻辑。
示例
public override void Participate(IGrainLifecycle lifecycle)
{
base.Participate(lifecycle);
lifecycle.Subscribe(this.GetType().FullName, GrainLifecycleStage.SetupState, OnSetupState);
}
在上面的示例中,Grain<T>
重写participate
方法,以告知生命周期在它的SetupState阶段,调用其OnSetupState方法。
在grain的构造中创建的组件,也可以参与生命周期,而不需要添加任何特殊的grain逻辑。由于grain的激活上下文(IGrainActivationContext
),包括grain的生命周期(IGrainActivationContext.ObservableLifecycle
),是在创建grain之前创建的,因此被容器给依赖注入grain中的任何组件,都可以参与grain的生命周期。
示例
使用工厂方法Create(..)
创建以下组件时,它们会参与grain的生命周期。这个逻辑可能存在于组件的构造函数中,但这会使组件在完全构建之前被添加到生命周期中,这可能是不安全的。
public class MyComponent : ILifecycleParticipant<IGrainLifecycle>
{
public static MyComponent Create(IGrainActivationContext context)
{
var component = new MyComponent();
component.Participate(context.ObservableLifecycle);
return component;
}
public void Participate(IGrainLifecycle lifecycle)
{
lifecycle.Subscribe<MyComponent>(GrainLifecycleStage.Activate, OnActivate);
}
private Task OnActivate(CancellationToken ct)
{
// Do stuff
}
}
通过使用Create(..)
工厂方法,在服务容器中注册上述组件,以组件作为依赖关系构造的任何grain,都将使组件参与其生命周期,而不会在grain中使用任何特殊逻辑。
在容器中注册组件
services.AddTransient<MyComponent>(sp =>
MyComponent.Create(sp.GetRequiredService< IGrainActivationContext>());
带有依赖注入组件的grain
public class MyGrain : Grain, IMyGrain
{
private readonly MyComponent component;
public MyGrain(MyComponent component)
{
this. component = component;
}
}