Vue d’ensemble du cycle de vie des silos Orleans

Les silos Orleans utilisent un cycle de vie observable pour le démarrage et l’arrêt ordonnés des systèmes Orleans, ainsi que des composants de couche d’application. Pour plus d’informations sur les détails d’implémentation, consultez Cycle de vie Orleans.

Étapes

Les clients de silo et de cluster Orleans utilisent un ensemble commun d’étapes de cycle de vie de service.

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

Journalisation

En raison de l’inversion du contrôle, les participants rejoignent le cycle de vie au lieu que le cycle de vie ait un ensemble centralisé d’étapes d’initialisation et, en examinant le code, l’ordre de démarrage/d’arrêt n’est pas toujours clair. Pour vous aider à résoudre ce problème, la journalisation a été ajoutée avant le démarrage du silo pour signaler les composants qui participent à chaque étape. Ces journaux sont enregistrés au niveau de journalisation Informations sur l’enregistreur d’événements Orleans.Runtime.SiloLifecycleSubject. Exemple :

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"

En outre, les informations de minutage et d’erreur sont journalisées de la même façon pour chaque composant par étape. Exemple :

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

Participation au cycle de vie des silos

La logique d’application peut participer au cycle de vie du silo en inscrivant un service participant dans le conteneur de service du silo. Le service doit être inscrit en tant que ILifecycleParticipant<TLifecycleObservable>T est un ISiloLifecycle.

public interface ISiloLifecycle : ILifecycleObservable
{
}

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

Quand le silo démarre, tous les participants (ILifecycleParticipant<ISiloLifecycle>) du conteneur sont autorisés à participer en appelant leur comportement ILifecycleParticipant<TLifecycleObservable>.Participate. Une fois que tous ont eu la possibilité de participer, le cycle de vie observable du silo démarre toutes les étapes dans l’ordre.

Exemple

Avec l’introduction du cycle de vie des silos, les fournisseurs de démarrage, qui autorisaient les développeurs d’applications à injecter une logique dans la phase d’initialisation du fournisseur, ne sont plus nécessaires, car la logique d’application peut désormais être injectée dans n’importe quelle phase du démarrage du silo. Néanmoins, nous avons ajouté une façade de « tâche de démarrage » pour faciliter la transition pour les développeurs qui utilisaient les fournisseurs de démarrage. Comme exemple de la façon dont les composants qui participent au cycle de vie du silo peuvent être développés, nous allons examiner la façade de la tâche de démarrage.

La tâche de démarrage doit uniquement hériter de ILifecycleParticipant<ISiloLifecycle> et abonner la logique d’application au cycle de vie du silo dans la phase spécifiée.

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

À partir de l’implémentation ci-dessus, nous pouvons voir que dans l’appel Participate(...), elle s’abonne au cycle de vie du silo dans la phase configurée, en passant le rappel d’application plutôt que sa logique d’initialisation. Les composants qui doivent être initialisés dans une phase donnée fournissent leur rappel, mais le modèle est le même. Maintenant que nous avons un élément StartupTask qui garantit que le hook de l’application est appelé dans la phase configurée, nous devons nous assurer que l’élément StartupTask participera au cycle de vie du silo.

Pour cela, il nous suffit de l’inscrire dans le conteneur. Nous réalisons cela avec une fonction d’extension sur 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;
}

En inscrivant StartupTask dans le conteneur de service du silo comme interface de marqueur ILifecycleParticipant<ISiloLifecycle>, cela signale au silo que ce composant doit prendre part au cycle de vie du silo.