Ereignis in .NET.NET Aspire
In .NET.NET Aspireermöglicht das Ereignis-Management, Ereignisse während der verschiedenen Lebenszyklen eines App-Hostszu veröffentlichen und zu abonnieren. Ereignisverarbeitung ist flexibler als Lebenszyklusereignisse. Beide ermöglichen es Ihnen, beliebigen Code während Ereignisrückrufen auszuführen, aber die Ereignisverwaltung bietet eine feinere Kontrolle über das Timing von Ereignissen, die Veröffentlichung und unterstützt benutzerdefinierte Ereignisse.
Die Ereignismechanismen in .NET.NET Aspire sind Teil des 📦Aspire.Hosting--NuGet-Pakets. Dieses Paket stellt eine Reihe von Schnittstellen und Klassen im Aspire.Hosting.Eventing Namespace bereit, die Sie zum Veröffentlichen und Abonnieren von Ereignissen in Ihrem .NET.NET Aspire App-Hostprojekt verwenden. Die Ereignisverwaltung ist ausschließlich auf den App-Host selbst und die darin enthaltenen Ressourcen begrenzt.
In diesem Artikel erfahren Sie, wie Sie die Ereignisfunktionen in .NET.NET Aspireverwenden.
App-Host-Eventverwaltung
Die folgenden Ereignisse sind im App-Host verfügbar und treten in der folgenden Reihenfolge auf:
- BeforeStartEvent: Dieses Ereignis wird vor dem Start des App-Hosts ausgelöst.
- AfterEndpointsAllocatedEvent: Dieses Ereignis wird ausgelöst, nachdem der App-Host Endpunkte zugewiesen hat.
- AfterResourcesCreatedEvent: Dieses Ereignis wird ausgelöst, nachdem der App-Host Ressourcen erstellt hat.
Alle vorhergehenden Ereignisse sind den App-Host-Lebenszyklenähnlich. Das heißt, eine Implementierung der IDistributedApplicationLifecycleHook könnte diese Ereignisse genauso behandeln. Mit der Ereignis-API können Sie jedoch beliebigen Code ausführen, wenn diese Ereignisse ausgelöst werden, und Sie können benutzerdefinierte Ereignisse definieren – jedes Ereignis, das die IDistributedApplicationEvent Schnittstelle implementiert.
Abonnieren von App-Hostereignissen
Verwenden Sie die Ereignis-API, um die integrierten App-Hostereignisse zu abonnieren. Nachdem Sie über eine verteilte Anwendungs-Generator-Instanz verfügen, gehen Sie zur IDistributedApplicationBuilder.Eventing-Eigenschaft, und rufen Sie die Subscribe<T>(Func<T,CancellationToken,Task>)-API auf. Betrachten Sie den folgenden Beispiel-App-Host Program.cs Datei:
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();
Der vorangehende Code basiert auf der Startvorlage mit dem Hinzufügen der Aufrufe der Subscribe
-API. Die Subscribe<T>
-API gibt eine DistributedApplicationEventSubscription-Instanz zurück, die Sie zum Abmelden vom Ereignis verwenden können. Es ist üblich, die zurückgegebenen Abonnements zu verwerfen, da Sie in der Regel kein Abonnement von Ereignissen kündigen müssen, da die gesamte App beim Herunterfahren des App-Hosts heruntergefahren wird.
Wenn der App-Host ausgeführt wird, sollte zum Zeitpunkt der Anzeige des .NET.NET Aspire Dashboards die folgende Protokollausgabe in der Konsole angezeigt werden:
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.
Die Protokollausgabe bestätigt, dass Ereignishandler in der Reihenfolge der App-Hostlebenszyklusereignisse ausgeführt werden. Die Abonnementbestellung wirkt sich nicht auf die Ausführungsreihenfolge aus. Die BeforeStartEvent
wird zuerst ausgelöst, gefolgt von AfterEndpointsAllocatedEvent
und schließlich AfterResourcesCreatedEvent
.
Ressourcen-Ereignisverwaltung
Zusätzlich zu den App-Hostereignissen können Sie auch Ressourcenereignisse abonnieren. Ressourcenereignisse werden für eine einzelne Ressource spezifisch ausgelöst. Ressourcenereignisse werden als Implementierungen der IDistributedApplicationResourceEvent Schnittstelle definiert. Die folgenden Ressourcenereignisse sind in der aufgeführten Reihenfolge verfügbar:
- ConnectionStringAvailableEvent: Wird ausgelöst, wenn eine Verbindungszeichenfolge für eine Ressource verfügbar wird.
- BeforeResourceStartedEvent: Ausgelöst, bevor der Orchestrator eine neue Ressource startet.
- ResourceReadyEvent: Wird ausgelöst, wenn eine Ressource zunächst in einen betriebsbereiten Zustand wechselt.
Abonnieren von Ressourcenereignissen
Um Ressourcenereignisse zu abonnieren, verwenden Sie die Ereignis-API. Sobald Sie eine Instanz des verteilten Anwendungs-Generators haben, gehen Sie zur Eigenschaft IDistributedApplicationBuilder.Eventing und rufen Sie die API Subscribe<T>(IResource, Func<T,CancellationToken,Task>) auf. Betrachten Sie den folgenden Beispiel-App-Host Program.cs Datei:
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();
Der vorangehende Code abonniert die Ereignisse ResourceReadyEvent
, ConnectionStringAvailableEvent
und BeforeResourceStartedEvent
an der Ressource cache
. Wenn AddRedis aufgerufen wird, wird eine IResourceBuilder<T> zurückgegeben, bei der T
eine RedisResourceist. Der Ressourcen-Generator macht die Ressource als IResourceBuilder<T>.Resource-Eigenschaft verfügbar. Die betreffende Ressource wird dann an die Subscribe
-API übergeben, um Events auf der Ressource zu abonnieren.
Wenn der App-Host ausgeführt wird, sollten Sie zum Zeitpunkt der Anzeige des .NET.NET Aspire Dashboards die folgende Protokollausgabe in der Konsole sehen:
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.
Anmerkung
Einige Ereignisse sind blockierend. Wenn das BeforeResourceStartEvent
beispielsweise veröffentlicht wird, wird der Start der Ressource blockiert, bis alle Abonnements für dieses Ereignis auf einer bestimmten Ressource ausgeführt wurden. Ob ein Ereignis blockierend ist oder nicht, hängt davon ab, wie es veröffentlicht wird (siehe den folgenden Abschnitt).
Veröffentlichen von Ereignissen
Wenn Sie eines der integrierten Ereignisse abonnieren, müssen Sie das Ereignis nicht selbst veröffentlichen, da der App-Host-Orchestrator die integrierten Ereignisse für Sie veröffentlicht. Sie können jedoch benutzerdefinierte Ereignisse mit der Ereignis-API veröffentlichen. Um ein Ereignis zu veröffentlichen, müssen Sie zuerst ein Ereignis als Implementierung der IDistributedApplicationEvent- oder IDistributedApplicationResourceEvent-Schnittstelle definieren. Sie müssen bestimmen, welche Schnittstelle basierend darauf implementiert werden soll, ob es sich bei dem Ereignis um ein globales App-Hostereignis oder um ein ressourcenspezifisches Ereignis handelt.
Anschließend können Sie das Ereignis abonnieren und veröffentlichen, indem Sie eine der folgenden APIs aufrufen:
- PublishAsync<T>(T, CancellationToken): Veröffentlicht ein Ereignis für alle Abonnenten des bestimmten Ereignistyps.
- PublishAsync<T>(T, EventDispatchBehavior, CancellationToken): Veröffentlicht ein Ereignis für alle Abonnenten des bestimmten Ereignistyps mit einem angegebenen Versandverhalten.
Bereitstellen einer EventDispatchBehavior
Wenn Ereignisse verteilt werden, können Sie steuern, wie die Ereignisse an Abonnenten verteilt werden. Das Ereignisversandverhalten wird mit dem EventDispatchBehavior
Enum angegeben. Die folgenden Verhaltensweisen sind verfügbar:
- EventDispatchBehavior.BlockingSequential: Löst Ereignisse sequenziell aus und blockiert sie, bis sie alle verarbeitet werden.
- EventDispatchBehavior.BlockingConcurrent: Löst Ereignisse gleichzeitig aus und blockiert sie, bis sie alle verarbeitet werden.
- EventDispatchBehavior.NonBlockingSequential: Löst Ereignisse sequenziell aus, blockiert aber nicht.
- EventDispatchBehavior.NonBlockingConcurrent: Löst Ereignisse gleichzeitig aus und blockiert dabei nicht.
Das Standardverhalten ist EventDispatchBehavior.BlockingSequential
. Um dieses Verhalten außer Kraft zu setzen, stellen Sie beim Aufrufen einer Veröffentlichungs-API wie PublishAsyncdas gewünschte Verhalten als Argument bereit.