Orleans 生命周期概述

一些 Orleans 行为非常复杂,以至于它们需要有序的启动和关闭。 一些具有这种行为的组件包括 grain、silo 和客户端。 为解决此问题,已引入了常规组件生命周期模式。 该模式包括可观察的生命周期(负责在组件的启动和关闭阶段发出信号),以及生命周期观察者(负责在特定阶段执行启动或关闭操作)。

有关详细信息,请参阅 Grain 生命周期Silo 生命周期

可观察的生命周期

需要有序启动和关闭的组件可以使用可观察的生命周期,这种生命周期使其他组件能够观察生命周期并在启动或关闭期间达到某个阶段时接收通知。

public interface ILifecycleObservable
{
    IDisposable Subscribe(
        string observerName,
        int stage,
        ILifecycleObserver observer);
}

订阅调用会注册一个观察者,以便在启动或停止期间达到某个阶段时接收通知。 观察者的名称用于进行报告。 阶段指示了将在启动/关闭序列中的哪个点通知观察者。 生命周期的每个阶段都是可观察的。 在启动和停止期间达到一个阶段时,将通知所有观察者。 阶段按升序启动,并按降序停止。 观察者可以通过释放返回的可释放对象来取消订阅。

生命周期观察者

需要参与另一个组件的生命周期的组件需要为其启动和关闭行为提供挂钩,并订阅可观察的生命周期的特定阶段。

public interface ILifecycleObserver
{
    Task OnStart(CancellationToken ct);
    Task OnStop(CancellationToken ct);
}

在启动/关闭期间达到所订阅的阶段时会调用 ILifecycleObserver.OnStartILifecycleObserver.OnStop

实用程序

为方便起见,已为常见生命周期使用模式创建了帮助程序函数。

扩展

扩展函数用于订阅可观察的生命周期,这种生命周期不要求订阅组件实现 ILifecycleObserver。 相反,这些允许组件传入要在订阅阶段调用的 lambda 或 members 函数。

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();
    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));
    }
}