某些 Orleans 行为非常复杂,需要有序启动和关闭。 具有此类行为的组件包括谷物、筒仓和客户端。 为了解决此问题, Orleans 引入了常规组件生命周期模式。 此模式由一个可观察的生命周期组成,负责在组件启动和关闭的各个阶段发出信号,以及由负责在特定阶段执行启动或关闭操作的生命周期观察者组成。
可观测生命周期
需要有序启动和关闭的组件可以使用可观察的生命周期。 这样,其他组件就可以观察生命周期,并在启动或关闭期间达到特定阶段时接收通知。
public interface ILifecycleObservable
{
IDisposable Subscribe(
string observerName,
int stage,
ILifecycleObserver observer);
}
通过订阅方法调用,在启动或关闭期间达到某个阶段时注册一个观察者,以接收通知。 观察者的名称用于报告目的。 阶段指示观察者接收通知的启动/关闭序列中的哪个时间点。 每个生命周期阶段都是可观测的。 在启动和关闭期间达到某个阶段时,会通知所有观察者。 阶段以升序开始,并按降序停止。 观察者可以通过处理返回的一次性对象来取消订阅。
生命周期观察者
需要参与另一个组件的生命周期的组件必须为其启动和关闭行为提供挂钩,并订阅可观察生命周期的特定阶段。
public interface ILifecycleObserver
{
Task OnStart(CancellationToken ct);
Task OnStop(CancellationToken ct);
}
在启动或关闭期间达到订阅的阶段时,ILifecycleObserver.OnStart和ILifecycleObserver.OnStop都会被调用。
公用事业
为了方便使用常见的生命周期模式,存在辅助函数。
插件
扩展函数提供了一种方法,可以订阅可观察的生命周期,而无需订阅组件实现 ILifecycleObserver
。 这些组件允许传入 lambda 或成员函数,以便在订阅阶段调用。
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);
生命周期参与
某些扩展点需要一种方法来识别哪些组件有兴趣参与生命周期。 生命周期参与者标记接口用于此目的。 探索孤岛和谷物生命周期时,将详细介绍其使用情况。
public interface ILifecycleParticipant<TLifecycleObservable>
where TLifecycleObservable : ILifecycleObservable
{
void Participate(TLifecycleObservable lifecycle);
}
示例:
在Orleans生命周期测试中,下面是一个在多个阶段参与可观察生命周期的组件示例。
enum TestStages
{
Down,
Initialize,
Configure,
Run,
};
class MultiStageObserver : ILifecycleParticipant<ILifecycleObservable>
{
public Dictionary<TestStages,bool> Started { get; } = new();
public Dictionary<TestStages, bool> Stopped { get; } = new();
private Task OnStartStage(TestStages stage)
{
Started[stage] = true;
return Task.CompletedTask;
}
private Task OnStopStage(TestStages stage)
{
Stopped[stage] = true;
return Task.CompletedTask;
}
public void Participate(ILifecycleObservable lifecycle)
{
lifecycle.Subscribe<MultiStageObserver>(
(int)TestStages.Down,
_ => OnStartStage(TestStages.Down),
_ => OnStopStage(TestStages.Down));
lifecycle.Subscribe<MultiStageObserver>(
(int)TestStages.Initialize,
_ => OnStartStage(TestStages.Initialize),
_ => OnStopStage(TestStages.Initialize));
lifecycle.Subscribe<MultiStageObserver>(
(int)TestStages.Configure,
_ => OnStartStage(TestStages.Configure),
_ => OnStopStage(TestStages.Configure));
lifecycle.Subscribe<MultiStageObserver>(
(int)TestStages.Run,
_ => OnStartStage(TestStages.Run),
_ => OnStopStage(TestStages.Run));
}
}