一些Orleans行为足够复杂,需要有序地启动和关闭。具有此种行为的一些组件包括grain、silo和客户端。为了解决此问题,引入了一个通用的组件生命周期模式。这个模式包含一个可观察的生命周期,负责在组件的启动和关闭阶段发出信号,以及生命周期观察者,它负责在特定阶段执行启动或关闭操作。
另请参阅Grain Lifecycle和Silo Lifecycle。
需要有序地启动和关闭的组件,可以使用可观察的生命周期,允许其他组件在启动或关闭期间到达某个阶段时,观察生命周期并接收通知。
public interface ILifecycleObservable
{
IDisposable Subscribe(string observerName, int stage, ILifecycleObserver observer);
}
调用Subscribe
注册了一个观察者,当在启动或停止期间到达某个阶段时,来通知观察者。观察者名称(observerName)
用于报告的目的。stage
指示了在启动/关闭序列中的哪一个阶段要通知观察者。生命周期的每个阶段都是可观察的。在启动和停止阶段期间到达某个stage
时,将通知所有观察者。阶段按升序开始,并按降序停止。观察者可以通过销毁返回的IDisposable
,来取消订阅。
需要参与另一个组件生命周期的组件,需要为它们的启动和关闭行为提供钩子,并订阅可观察生命周期的特定阶段。
public interface ILifecycleObserver
{
Task OnStart(CancellationToken ct);
Task OnStop(CancellationToken ct);
}
在启动/关闭期间,在到达订阅的阶段时,将调用OnStart/OnStop
。
为方便起见,已为常见的生命周期使用模式,创建了一些帮助方法。
有用于订阅可观察生命周期的扩展方法,它不要求订阅组件实现ILifecycleObserver。相反,这些扩展方法允许组件传入lambdas或成员函数,以在订阅阶段调用。
IDisposable Subscribe(this ILifecycleObservable observable, string observerName, int stage, Func<CancellationToken, Task> onStart, Func<CancellationToken, Task> onStop);
IDisposable Subscribe(this ILifecycleObservable observable, string observerName, int stage, Func<CancellationToken, Task> onStart);
类似的扩展函数,允许使用泛型类型参数,来代替观察者名称。
IDisposable Subscribe<TObserver>(this ILifecycleObservable observable, int stage, Func<CancellationToken, Task> onStart, Func<CancellationToken, Task> onStop);
IDisposable Subscribe<TObserver>(this ILifecycleObservable observable, int stage, Func<CancellationToken, Task> onStart);
一些可扩展性点需要一种方法来识别哪些组件对参与生命周期感兴趣。为此,引入了生命周期参与者的标识接口。在探索silo和grain的生命周期时,将详细介绍如何使用它。
public interface ILifecycleParticipant<TLifecycleObservable>
where TLifecycleObservable : ILifecycleObservable
{
void Participate(TLifecycleObservable lifecycle);
}
从我们的生命周期测试中,下面是一个组件的示例,该组件在生命周期的多个阶段,参与了可观察的生命周期。
enum TestStages
{
Down,
Initialize,
Configure,
Run,
}
class MultiStageObserver : ILifecycleParticipant<ILifecycleObservable>
{
public Dictionary<TestStages,bool> Started { get; } = new Dictionary<TestStages, bool>();
public Dictionary<TestStages, bool> Stopped { get; } = new Dictionary<TestStages, bool>();
private Task OnStartStage(TestStages stage)
{
this.Started[stage] = true;
return Task.CompletedTask;
}
private Task OnStopStage(TestStages stage)
{
this.Stopped[stage] = true;
return Task.CompletedTask;
}
public void Participate(ILifecycleObservable lifecycle)
{
lifecycle.Subscribe<MultiStageObserver>((int)TestStages.Down, ct => OnStartStage(TestStages.Down), ct => OnStopStage(TestStages.Down));
lifecycle.Subscribe<MultiStageObserver>((int)TestStages.Initialize, ct => OnStartStage(TestStages.Initialize), ct => OnStopStage(TestStages.Initialize));
lifecycle.Subscribe<MultiStageObserver>((int)TestStages.Configure, ct => OnStartStage(TestStages.Configure), ct => OnStopStage(TestStages.Configure));
lifecycle.Subscribe<MultiStageObserver>((int)TestStages.Run, ct => OnStartStage(TestStages.Run), ct => OnStopStage(TestStages.Run));
}
}