Orleans Přehled životního cyklu sila

Orleans sila používají pozorovatelný životní cyklus pro seřazené spouštění a vypínání Orleans systémů a také komponenty aplikační vrstvy. Další informace o podrobnostech implementace najdete v tématu Orleans životní cyklus.

FÁZE

Orleans Klienti silo a clusteru používají společnou sadu fází životního cyklu služby.

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

Protokolování

Vzhledem k tomu, že se účastníci připojují k životnímu cyklu místo toho, aby měli centralizovanou sadu inicializačních kroků, není vždy jasné z kódu, jaký je pořadí spuštění/vypnutí. Abychom to mohli vyřešit, bylo protokolování přidáno před spuštěním sila, aby se ohlásily, které komponenty se v jednotlivých fázích účastní. Tyto protokoly se zaznamenávají na úrovni protokolu informací v protokolovacím nástroje Orleans.Runtime.SiloLifecycleSubject . Například:

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"

Kromě toho jsou informace o časování a chybách podobně protokolovány pro každou komponentu v jednotlivých fázích. Například:

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."

Účast na životním cyklu sila

Logika aplikace se může účastnit životního cyklu sila registrací zúčastněné služby v kontejneru služby silo. Služba musí být registrována jako místo ILifecycleParticipant<TLifecycleObservable>T , kde je ISiloLifecycle.

public interface ISiloLifecycle : ILifecycleObservable
{
}

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

Když se silo spustí, všichni účastníci (ILifecycleParticipant<ISiloLifecycle>) v kontejneru se budou moci účastnit voláním jejich ILifecycleParticipant<TLifecycleObservable>.Participate chování. Jakmile se všichni mohli zúčastnit, bude pozorovatelný životní cyklus silo začínat všechny fáze v pořadí.

Příklad

Se zavedením životního cyklu sila už nejsou poskytovatelé bootstrap, kteří vývojáři aplikací umožnili vkládání logiky ve fázi inicializace zprostředkovatele, protože logika aplikace se teď dá vložit v jakékoli fázi spuštění sil. Přidali jsme však fasádu "spouštěcí úlohy", která vývojářům, kteří používali poskytovatele bootstrap, pomohla přechodu. Jako příklad, jak lze vyvíjet komponenty, které se účastní životního cyklu silo, se podíváme na fasádu spouštěcí úlohy.

Spouštěcí úloha musí zdědit ILifecycleParticipant<ISiloLifecycle> logiku aplikace a přihlásit ji k odběru životního cyklu sil v zadané fázi.

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

Z výše uvedené implementace vidíme, že ve Participate(...) volání se přihlásí k odběru životního cyklu sila v nakonfigurované fázi a předá zpětné volání aplikace místo jeho inicializační logiky. Komponenty, které je potřeba inicializovat v dané fázi, by poskytovaly zpětné volání, ale vzor je stejný. Teď, když máme jistotu StartupTask , že je volání háku aplikace volána v nakonfigurované fázi, musíme zajistit, aby StartupTask se účast v životním cyklu silu účastnila.

V takovém případě ho potřebujeme zaregistrovat pouze v kontejneru. Provedeme to pomocí funkce rozšíření na :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;
}

Registrací StartupTask v kontejneru služby silo jako rozhraní ILifecycleParticipant<ISiloLifecycle>značek tento signál pro silové rozhraní signalizuje, že se tato komponenta musí podílet na životním cyklu sila.