Orleans 定址接收器生命週期概觀

Orleans 定址接收器會針對 Orleans 系統的排序啟動和關閉,以及應用層元件使用可觀察的生命週期。 如需實作詳細資料的詳細資訊,請參閱Orleans 生命週期

階段

Orleans 定址接收器和叢集用戶端會使用一組常見的服務生命週期階段。

public static class ServiceLifecycleStage
{
    public const int First = int.MinValue;
    public const int RuntimeInitialize = 2_000;
    public const int RuntimeServices = 4_000;
    public const int RuntimeStorageServices = 6_000;
    public const int RuntimeGrainServices = 8_000;
    public const int ApplicationServices = 10_000;
    public const int BecomeActive = Active - 1;
    public const int Active = 20_000;
    public const int Last = int.MaxValue;
}

記錄

由於控制反轉,參與者會加入生命週期,而非具有某些一組集中式初始化步驟的生命週期,因此從程式碼看來,啟動/關機順序並不一定清楚。 為了協助解決此問題,在定址接收器啟動之前已新增記錄,以報告每個階段有哪些元件參與。 這些記錄會記錄在 Orleans.Runtime.SiloLifecycleSubject 記錄器的資訊記錄層級。 例如:

Information, Orleans.Runtime.SiloLifecycleSubject, "Stage 2000: Orleans.Statistics.PerfCounterEnvironmentStatistics, Orleans.Runtime.InsideRuntimeClient, Orleans.Runtime.Silo"

Information, Orleans.Runtime.SiloLifecycleSubject, "Stage 4000: Orleans.Runtime.Silo"

Information, Orleans.Runtime.SiloLifecycleSubject, "Stage 10000: Orleans.Runtime.Versions.GrainVersionStore, Orleans.Storage.AzureTableGrainStorage-Default, Orleans.Storage.AzureTableGrainStorage-PubSubStore"

此外,時間與錯誤資訊會依階段針對每個元件記錄。 例如:

Information, Orleans.Runtime.SiloLifecycleSubject, "Lifecycle observer Orleans.Runtime.InsideRuntimeClient started in stage 2000 which took 33 Milliseconds."

Information, Orleans.Runtime.SiloLifecycleSubject, "Lifecycle observer Orleans.Statistics.PerfCounterEnvironmentStatistics started in stage 2000 which took 17 Milliseconds."

定址接收器生命週期參與

應用程式邏輯可以藉由在定址接收器的服務容器中註冊參與服務,以參與定址接收器的生命週期。 服務必須註冊為 ILifecycleParticipant<TLifecycleObservable>,其中 TISiloLifecycle

public interface ISiloLifecycle : ILifecycleObservable
{
}

public interface ILifecycleParticipant<TLifecycleObservable>
    where TLifecycleObservable : ILifecycleObservable
{
    void Participate(TLifecycleObservable lifecycle);
}

當定址接收器啟動時,容器中的所有參與者 (ILifecycleParticipant<ISiloLifecycle>) 將可以藉由呼叫其 ILifecycleParticipant<TLifecycleObservable>.Participate 行為來參與。 一旦所有參與者有機會參與,定址接收器的可觀察生命週期將會依序啟動所有階段。

範例

透過引進定址接收器生命週期,可用來允許應用程式開發人員在提供者初始化階段插入邏輯的啟動程式提供者已不再需要,因為應用程式邏輯現在可以在定址接收器啟動的任何階段插入。 不過,我們新增了「啟動工作」外觀,可協助針對已使用啟動程式提供者的開發人員進行轉換。 作為如何開發元件以參與定址接收器生命週期的範例,我們將探討啟動工作外觀。

啟動工作只需要繼承自 ILifecycleParticipant<ISiloLifecycle>,並在指定的階段訂閱定址接收器生命週期的應用程式邏輯。

class StartupTask : ILifecycleParticipant<ISiloLifecycle>
{
    private readonly IServiceProvider _serviceProvider;
    private readonly Func<IServiceProvider, CancellationToken, Task> _startupTask;
    private readonly int _stage;

    public StartupTask(
        IServiceProvider serviceProvider,
        Func<IServiceProvider, CancellationToken, Task> startupTask,
        int stage)
    {
        _serviceProvider = serviceProvider;
        _startupTask = startupTask;
        _stage = stage;
    }

    public void Participate(ISiloLifecycle lifecycle)
    {
        lifecycle.Subscribe<StartupTask>(
            _stage,
            cancellation => _startupTask(_serviceProvider, cancellation));
    }
}

從上述實作中,我們可以看到在 Participate(...) 呼叫中,期會訂閱設定階段的定址接收器生命週期,傳遞應用程式回呼,而非其初始化邏輯。 需要在指定階段初始化的元件會提供其回呼,但模式相同。 既然我們已經擁有 StartupTask,以確保在已設定階段呼叫應用程式的勾點,我們必須確保 StartupTask 參與定址接收器生命週期。

為此,我們只需要在容器中進行註冊。 我們會使用 ISiloHostBuilder 上的擴充函式來執行此作業:

public static ISiloHostBuilder AddStartupTask(
    this ISiloHostBuilder builder,
    Func<IServiceProvider, CancellationToken, Task> startupTask,
    int stage = ServiceLifecycleStage.Active)
{
    builder.ConfigureServices(services =>
        services.AddTransient<ILifecycleParticipant<ISiloLifecycle>>(
            serviceProvider =>
                new StartupTask(
                    serviceProvider, startupTask, stage)));

    return builder;
}

藉由將定址接收器服務容器中的 StartupTask 註冊為標記介面 ILifecycleParticipant<ISiloLifecycle>,這會向定址接收器發出信號,指出此元件需要參與定址接收器生命週期。