Condividi tramite


Organizzazione di eventi in .NET.NET Aspire

In .NET.NET Aspire, l'eventing consente di pubblicare e sottoscrivere eventi durante i diversi cicli di vita dell'host dell'applicazione . Il sistema di eventi è più flessibile rispetto agli eventi del ciclo di vita. Entrambi consentono di eseguire codice arbitrario durante i callback degli eventi, ma l'eventing offre un controllo più preciso della tempistica degli eventi, della pubblicazione e supporta eventi personalizzati.

I meccanismi di gestione degli eventi in .NET.NET Aspire fanno parte del pacchetto NuGet 📦Aspire.Hosting. Questo pacchetto fornisce un set di interfacce e classi nello spazio dei nomi Aspire.Hosting.Eventing che si usano per pubblicare e abbonarsi agli eventi nel progetto host dell'app .NET.NET Aspire. La gestione degli eventi è limitata all'host dell'app stesso e alle risorse all'interno dell'app.

Questo articolo illustra come usare le funzionalità di gestione degli eventi in .NET.NET Aspire.

Eventi di hosting dell'app

Gli eventi seguenti sono disponibili nell'host dell'app e si verificano nell'ordine seguente:

  1. BeforeStartEvent: questo evento viene generato prima dell'avvio dell'host dell'app.
  2. AfterEndpointsAllocatedEvent: Questo evento viene generato dopo che l'host dell'app ha allocato gli endpoint.
  3. AfterResourcesCreatedEvent: Questo evento viene generato dopo la creazione delle risorse dell'host dell'app.

Tutti gli eventi precedenti sono analoghi ai cicli di vita dell'host dell'app . Ovvero, un'implementazione del IDistributedApplicationLifecycleHook potrebbe gestire questi eventi allo stesso modo. Con l'API di eventi, tuttavia, è possibile eseguire codice arbitrario quando questi eventi vengono attivati e definire eventi personalizzati, qualsiasi evento che implementa l'interfaccia IDistributedApplicationEvent.

Sottoscrivere gli eventi host dell'app

Per sottoscrivere gli eventi host dell'app predefiniti, usare l'API di creazione di eventi. Dopo aver creato un'istanza di Generatore di applicazioni distribuite, andare alla proprietà IDistributedApplicationBuilder.Eventing e chiamare l'API Subscribe<T>(Func<T,CancellationToken,Task>). Si consideri il file di host dell'app di esempio seguente Program.cs:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache");

var apiService = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");

builder.AddProject<Projects.AspireApp_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithReference(cache)
    .WaitFor(cache)
    .WithReference(apiService)
    .WaitFor(apiService);

builder.Eventing.Subscribe<BeforeStartEvent>(
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("1. BeforeStartEvent");

        return Task.CompletedTask;
    });

builder.Eventing.Subscribe<AfterEndpointsAllocatedEvent>(
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("2. AfterEndpointsAllocatedEvent");

        return Task.CompletedTask;
    });

builder.Eventing.Subscribe<AfterResourcesCreatedEvent>(
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("3. AfterResourcesCreatedEvent");

        return Task.CompletedTask;
    });

builder.Build().Run();

Il codice precedente si basa sul modello di avvio con l'aggiunta delle chiamate all'API Subscribe. L'API Subscribe<T> restituisce un'istanza di DistributedApplicationEventSubscription che è possibile usare per annullare la sottoscrizione all'evento. È comune scartare le sottoscrizioni restituite, poiché in genere non è necessario annullare la sottoscrizione agli eventi, dato che l'intera app viene chiusa quando l'host dell'app viene arrestato.

Non appena l'host dell'app viene eseguito e il dashboard .NET.NET Aspire viene visualizzato, nella console si dovrebbe vedere il seguente output del log:

info: Program[0]
      1. BeforeStartEvent
info: Aspire.Hosting.DistributedApplication[0]
      Aspire version: 9.0.0
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
      Application host directory is: ..\AspireApp\AspireApp.AppHost
info: Program[0]
      2. AfterEndpointsAllocatedEvent
info: Aspire.Hosting.DistributedApplication[0]
      Now listening on: https://localhost:17178
info: Aspire.Hosting.DistributedApplication[0]
      Login to the dashboard at https://localhost:17178/login?t=<YOUR_TOKEN>
info: Program[0]
      3. AfterResourcesCreatedEvent
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application started. Press Ctrl+C to shut down.

L'output del log conferma che i gestori degli eventi vengono eseguiti nell'ordine degli eventi del ciclo di vita dell'host dell'app. L'ordine di sottoscrizione non influisce sull'ordine di esecuzione. Il BeforeStartEvent viene attivato per primo, seguito da AfterEndpointsAllocatedEvente infine AfterResourcesCreatedEvent.

Eventi delle risorse

Oltre agli eventi host dell'applicazione, è anche possibile abbonarsi agli eventi delle risorse. Gli eventi delle risorse vengono generati specificamente per una singola risorsa. Gli eventi delle risorse vengono definiti come implementazioni dell'interfaccia IDistributedApplicationResourceEvent. Gli eventi di risorsa seguenti sono disponibili nell'ordine elencato:

  1. ConnectionStringAvailableEvent: Attivato quando una stringa di connessione è disponibile per una risorsa.
  2. BeforeResourceStartedEvent: generato prima che l'orchestratore avvii una nuova risorsa.
  3. ResourceReadyEvent: Sollevato quando una risorsa passa per la prima volta a uno stato pronto.

Iscriversi agli eventi delle risorse

Per iscriversi agli eventi delle risorse, usare l'API di eventi. Dopo aver creato un'istanza di costruttore di applicazioni distribuite, accedi alla proprietà IDistributedApplicationBuilder.Eventing e chiama l'API Subscribe<T>(IResource, Func<T,CancellationToken,Task>). Si consideri il file di host dell'app di esempio seguente Program.cs:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

var builder = DistributedApplication.CreateBuilder(args);

var cache = builder.AddRedis("cache");

builder.Eventing.Subscribe<ResourceReadyEvent>(
    cache.Resource,
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("3. ResourceReadyEvent");

        return Task.CompletedTask;
    });

builder.Eventing.Subscribe<BeforeResourceStartedEvent>(
    cache.Resource,
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("2. BeforeResourceStartedEvent");

        return Task.CompletedTask;
    });

builder.Eventing.Subscribe<ConnectionStringAvailableEvent>(
    cache.Resource,
    static (@event, cancellationToken) =>
    {
        var logger = @event.Services.GetRequiredService<ILogger<Program>>();

        logger.LogInformation("1. ConnectionStringAvailableEvent");

        return Task.CompletedTask;
    });

var apiService = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");

builder.AddProject<Projects.AspireApp_Web>("webfrontend")
    .WithExternalHttpEndpoints()
    .WithReference(cache)
    .WaitFor(cache)
    .WithReference(apiService)
    .WaitFor(apiService);

builder.Build().Run();

Il codice precedente sottoscrive gli eventi ResourceReadyEvent, ConnectionStringAvailableEvente BeforeResourceStartedEvent nella risorsa cache. Quando viene chiamato AddRedis, restituisce un IResourceBuilder<T> in cui T è un RedisResource. Il generatore di risorse espone la risorsa come proprietà IResourceBuilder<T>.Resource. La risorsa in questione viene quindi passata all'API Subscribe per sottoscrivere gli eventi nella risorsa.

Quando l'host dell'app viene eseguito, entro il momento in cui viene visualizzato il dashboard .NET.NET Aspire, dovresti vedere il seguente output del log nella console:

info: Aspire.Hosting.DistributedApplication[0]
      Aspire version: 9.0.0
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application starting.
info: Aspire.Hosting.DistributedApplication[0]
      Application host directory is: ..\AspireApp\AspireApp.AppHost
info: Program[0]
      1. ConnectionStringAvailableEvent
info: Program[0]
      2. BeforeResourceStartedEvent
info: Program[0]
      3. ResourceReadyEvent
info: Aspire.Hosting.DistributedApplication[0]
      Now listening on: https://localhost:17222
info: Aspire.Hosting.DistributedApplication[0]
      Login to the dashboard at https://localhost:17222/login?t=<YOUR_TOKEN>
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application started. Press Ctrl+C to shut down.

Nota

Alcuni eventi sono bloccanti. Ad esempio, quando il BeforeResourceStartEvent viene pubblicato, l'avvio della risorsa verrà bloccato fino a quando tutte le sottoscrizioni per tale evento su una risorsa specifica abbiano completato l'esecuzione. Il blocco o meno di un evento dipende dalla modalità di pubblicazione (vedere la sezione seguente).

Pubblicare eventi

Quando si sottoscrive uno degli eventi predefiniti, non è necessario pubblicare l'evento manualmente perché l'agente di orchestrazione host dell'app gestisce la pubblicazione di eventi predefiniti per conto dell'utente. Tuttavia, è possibile pubblicare eventi personalizzati con l'API di eventi. Per pubblicare un evento, è necessario innanzitutto definire un evento come implementazione dell'interfaccia IDistributedApplicationEvent o IDistributedApplicationResourceEvent. È necessario determinare l'interfaccia da implementare in base al tipo di evento, se si tratta di un evento host globale dell'app o di un evento specifico della risorsa.

È quindi possibile sottoscrivere e pubblicare l'evento chiamando una delle API seguenti:

Fornire un EventDispatchBehavior

Quando gli eventi vengono inviati, è possibile controllare il modo in cui gli eventi vengono inviati ai sottoscrittori. Il comportamento di invio dell'evento viene specificato con l'enumerazione EventDispatchBehavior. Sono disponibili i comportamenti seguenti:

Il comportamento predefinito è EventDispatchBehavior.BlockingSequential. Per eseguire l'override di questo comportamento, quando si chiama un'API di pubblicazione, ad esempio PublishAsync, specificare il comportamento desiderato come argomento.