Udostępnij za pośrednictwem


Omówienie orkiestracji .NET.NET Aspire

.NET .NET Aspire udostępnia interfejsy API do wyrażania zasobów i zależności w aplikacji rozproszonej. Oprócz tych interfejsów API istnieją narzędzia, które umożliwiają kilka interesujących scenariuszy. Orkiestrator jest przeznaczony do celów lokalnego rozwoju i nie jest wspierany w środowiskach produkcyjnych.

Przed kontynuowaniem rozważ kilka typowych terminologii używanych w .NET.NET Aspire:

  • model aplikacji: kolekcja zasobów tworzących aplikację rozproszoną (DistributedApplication) zdefiniowana w przestrzeni nazw Aspire.Hosting.ApplicationModel. Aby uzyskać bardziej formalną definicję, zobacz Definiowanie modelu aplikacji.
  • host aplikacji/projekt orchestratora: projekt .NET, który organizuje model aplikacji , nazwany z użyciem sufiksu *.AppHost (zgodnie z konwencją).
  • zasób: zasób jest zależną częścią aplikacji, taką jak projekt .NET, kontener, plik wykonywalny, baza danych, pamięć podręczna lub usługa w chmurze. Reprezentuje ona dowolną część aplikacji, którą można zarządzać lub przywoływać.
  • Integracja: Integracja to pakiet NuGet dla hosta aplikacji , który modeluje zasób lub pakiet, który konfiguruje client do użycia w aplikacji użytkownika. Aby uzyskać więcej informacji, zobacz omówienie integracji .NET.NET Aspire.
  • Referencja: Referencja definiuje połączenie między zasobami, wyrażone jako zależność z użyciem interfejsu API WithReference. Aby uzyskać więcej informacji, zobacz Materiały referencyjne lub Istniejące zasoby referencyjne.

Notatka

Orkiestracja .NET.NET Aspirezostała zaprojektowana w celu zwiększenia doświadczenia w lokalnym rozwoju, upraszczając zarządzanie konfiguracją i wzajemnymi połączeniami aplikacji natywnej dla chmury. Chociaż jest to nieocenione narzędzie do rozwoju, nie jest przeznaczone do zastępowania systemów środowiska produkcyjnego, takich jak Kubernetes, które zostały specjalnie zaprojektowane, aby wyróżniać się w tym kontekście.

Definiowanie modelu aplikacji

.NET .NET Aspire umożliwia bezproblemowe tworzenie, aprowizowania, wdrażania, konfigurowania, testowania, uruchamiania i obserwowania aplikacji rozproszonych. Wszystkie te możliwości są osiągane dzięki wykorzystaniu modelu aplikacji , który przedstawia zasoby w rozwiązaniu .NET.NET Aspire i ich relacje. Te zasoby obejmują projekty, pliki wykonywalne, kontenery i usługi zewnętrzne oraz zasoby w chmurze, od których zależy Twoja aplikacja. W każdym rozwiązaniu .NET.NET Aspire istnieje wyznaczony projekt hosta aplikacji , w którym model aplikacji jest dokładnie zdefiniowany przy użyciu metod dostępnych w IDistributedApplicationBuilder. Ten konstruktor jest uzyskiwany przez wywołanie DistributedApplication.CreateBuilder.

// Create a new app model builder
var builder = DistributedApplication.CreateBuilder(args);

// TODO:
//   Add resources to the app model
//   Express dependencies between resources

builder.Build().Run();

Projekt hosta aplikacji

Projekt hosta aplikacji obsługuje uruchamianie wszystkich projektów, które są częścią projektu .NET.NET Aspire. Innymi słowy, odpowiada za organizowanie wszystkich aplikacji w modelu aplikacji. Sam projekt jest projektem wykonywalnym .NET, który odwołuje się do pakietu NuGet 📦Aspire.Hosting.AppHost, ustawia właściwość IsAspireHost na truei odwołuje się do zestawu SDK .NET.NET Aspire:

<Project Sdk="Microsoft.NET.Sdk">

    <Sdk Name="Aspire.AppHost.Sdk" Version="9.0.0" />
    
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net9.0</TargetFramework>
        <IsAspireHost>true</IsAspireHost>
        <!-- Omitted for brevity -->
    </PropertyGroup>

    <ItemGroup>
        <PackageReference Include="Aspire.Hosting.AppHost" Version="9.0.0" />
    </ItemGroup>

    <!-- Omitted for brevity -->

</Project>

Poniższy kod opisuje host aplikacji Program z dwoma odwołaniami do projektu i pamięcią podręczną Redis:

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.Build().Run();

Powyższy kod:

  • Tworzy nowego konstruktora modelu aplikacji przy użyciu metody CreateBuilder.
  • Dodaje zasób Rediscache o nazwie "cache" przy użyciu metody AddRedis.
  • Dodaje zasób projektu o nazwie "apiservice" przy użyciu metody AddProject.
  • Dodaje zasób projektu o nazwie "webfrontend" przy użyciu metody AddProject.
    • Określa, że projekt ma zewnętrzne punkty końcowe HTTP przy użyciu metody WithExternalHttpEndpoints.
    • Dodaje odwołanie do zasobu cache i oczekuje na przygotowanie go przy użyciu metod WithReference i WaitFor.
    • Dodaje odwołanie do zasobu apiservice i oczekuje na przygotowanie go przy użyciu metod WithReference i WaitFor.
  • Kompiluje i uruchamia model aplikacji przy użyciu metod Build i Run.

Kod przykładowy używa integracji hostingu .NET AspireRedis.

Aby ułatwić wizualizowanie relacji między projektem hosta aplikacji a opisanymi zasobami, należy wziąć pod uwagę następujący diagram:

Relacja między projektami w szablonie aplikacji początkowej .NET.NET Aspire.

Każdy zasób musi być unikatowo nazwany. Ten diagram przedstawia każdy zasób i relacje między nimi. Zasób kontenera nosi nazwę "cache", a zasoby projektu mają nazwę "apiservice" i "webfrontend". Projekt frontonu internetowego odwołuje się do projektów usługi pamięci podręcznej i interfejsu API. W przypadku wyrażania odwołań w ten sposób projekt frontonu internetowego mówi, że zależy to od tych dwóch zasobów, odpowiednio "pamięci podręcznej" i "apiservice".

Wbudowane typy zasobów

.NET .NET Aspire projekty składają się z zestawu zasobów. Rodzaje podstawowych zasobów w pakiecie NuGet 📦Aspire.Hosting.AppHost są opisane w poniższej tabeli:

Metoda Typ zasobu Opis
AddProject ProjectResource Projekt .NET, na przykład aplikacja internetowa ASP.NET Core.
AddContainer ContainerResource Obraz kontenera, taki jak obraz Docker.
AddExecutable ExecutableResource Plik wykonywalny, taki jak aplikacja Node.js.
AddParameter ParameterResource Zasób parametru, który może służyć do ekspresowych parametrów zewnętrznych.

Zasoby projektu reprezentują projekty .NET, które są częścią modelu aplikacji. Po dodaniu odwołania do projektu hosta aplikacji zestaw SDK .NET.NET Aspire generuje typ w przestrzeni nazw Projects dla każdego projektu, do którego odwołuje się odwołanie. Aby uzyskać więcej informacji, zobacz .NET.NET Aspire SDK: Dokumentacja projektu.

Aby dodać projekt do modelu aplikacji, użyj metody AddProject:

var builder = DistributedApplication.CreateBuilder(args);

// Adds the project "apiservice" of type "Projects.AspireApp_ApiService".
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");

Projekty można replikować i zwiększać rozmiar, dodając wiele wystąpień tego samego projektu do modelu aplikacji. Aby skonfigurować repliki, użyj metody WithReplicas:

var builder = DistributedApplication.CreateBuilder(args);

// Adds the project "apiservice" of type "Projects.AspireApp_ApiService".
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
                        .WithReplicas(3);

Powyższy kod dodaje trzy repliki zasobu projektu "apiservice" do modelu aplikacji. Aby uzyskać więcej informacji, zobacz .NET.NET Aspire panel sterowania: repliki zasobów.

Zasoby referencyjne

Odwołanie reprezentuje zależność między zasobami. Na przykład można sobie wyobrazić scenariusz, w którym frontend internetowy zależy od pamięci podręcznej Redis. Rozważmy poniższy przykład kodu C# dla aplikacji hosta Program:

var builder = DistributedApplication.CreateBuilder(args);

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

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

Zasób projektu "webfrontend" używa WithReference, aby dodać zależność od zasobu kontenera "cache". Te zależności mogą reprezentować łańcuchy połączenia lub informacje odnajdywania usługi. W poprzednim przykładzie zmienna środowiskowa jest wstrzykiwana do zasobu "webfrontend" o nazwie ConnectionStrings__cache. Ta zmienna środowiskowa zawiera parametry połączenia, których używa do nawiązywania połączenia z za pośrednictwemintegracji , na przykład .

Oczekiwanie na zasoby

W niektórych przypadkach możesz poczekać, aż zasób będzie gotowy przed uruchomieniem innego zasobu. Na przykład możesz poczekać, aż baza danych będzie gotowa przed uruchomieniem interfejsu API, który jest od niego zależny. Aby wyrazić tę zależność, użyj metody WaitFor:

var builder = DistributedApplication.CreateBuilder(args);

var postgres = builder.AddPostgres("postgres");
var postgresdb = postgres.AddDatabase("postgresdb");

builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
       .WithReference(postgresdb)
       .WaitFor(postgresdb);

W poprzednim kodzie zasób projektu "apiservice" czeka na zasób bazy danych "postgresdb", aby wszedł w stan KnownResourceStates.Running. Przykładowy kod pokazuje integrację .NET AspirePostgreSQL, ale ten sam wzorzec można zastosować do innych zasobów.

Inne przypadki mogą uzasadniać oczekiwanie, aż zasób ukończy swoje działanie, albo KnownResourceStates.Exited, albo KnownResourceStates.Finished, zanim rozpocznie się działanie zasobu zależnego. Aby poczekać na uruchomienie zasobu do ukończenia, użyj metody WaitForCompletion:

var builder = DistributedApplication.CreateBuilder(args);

var postgres = builder.AddPostgres("postgres");
var postgresdb = postgres.AddDatabase("postgresdb");

var migration = builder.AddProject<Projects.AspireApp_Migration>("migration")
                       .WithReference(postgresdb)
                       .WaitFor(postgresdb);

builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
       .WithReference(postgresdb)
       .WaitForCompletion(migration);

W poprzednim kodzie zasób projektu "apiservice" czeka na zakończenie działania zasobu projektu "migracja" przed rozpoczęciem. Zasób projektu "migracja" czeka, aż zasób bazy danych "postgresdb" pojawi się w KnownResourceStates.Running. Może to być przydatne w scenariuszach, w których chcesz uruchomić migrację bazy danych przed rozpoczęciem usługi interfejsu API, na przykład.

Interfejsy API do dodawania i wyrażania zasobów

.NET .NET Aspire integracje hostingu oraz integracje client są dostarczane jako pakiety NuGet, ale pełnią różne funkcje. Podczas gdy client integracje zapewniają konfigurację biblioteki client do korzystania z aplikacji poza zakresem hosta aplikacji, hostowanie integracji udostępniają interfejsy API do wyrażania zasobów i zależności w hoście aplikacji. Aby uzyskać więcej informacji, zajrzyj do przeglądu integracji .NET.NET Aspire: obowiązki integracyjne.

Zasoby kontenera express

Aby wyrazić ContainerResource, należy dodać go do wystąpienia IDistributedApplicationBuilder, wywołując metodę AddContainer.

var builder = DistributedApplication.CreateBuilder(args);

var ollama = builder.AddContainer("ollama", "ollama/ollama")
    .WithBindMount("ollama", "/root/.ollama")
    .WithBindMount("./ollamaconfig", "/usr/config")
    .WithHttpEndpoint(port: 11434, targetPort: 11434, name: "ollama")
    .WithEntrypoint("/usr/config/entrypoint.sh")
    .WithContainerRuntimeArgs("--gpus=all");

Aby uzyskać więcej informacji, zobacz obsługę GPU na Docker Desktop.

Powyższy kod dodaje zasób kontenera o nazwie "ollama" z obrazem ollama/ollama. Zasób kontenera jest skonfigurowany z wieloma punktami montowania, nazwanym punktem końcowym HTTP, punktem wejścia rozpoznawanym jako skrypt powłoki Unix oraz argumentami uruchomieniowymi kontenera wykorzystującymi metodę WithContainerRuntimeArgs.

Dostosowywanie zasobów kontenera

Wszystkie podklasy ContainerResource można dostosować do Twoich konkretnych wymagań. Może to być przydatne w przypadku korzystania z hostowania integracji modelujących zasób kontenera, ale wymaga modyfikacji. Jeśli masz IResourceBuilder<ContainerResource>, możesz łączyć wywołania do dowolnego z dostępnych interfejsów API, aby zmodyfikować zasób kontenera. .NET .NET Aspire zasoby kontenera zwykle wskazują przypięte tagi, ale możesz chcieć użyć tagu latest zamiast tego.

Aby to ułatwić, wyobraź sobie scenariusz, w którym korzystasz z integracji .NET AspireRedis. Jeżeli integracja Redis opiera się na tagu 7.4 i chcesz zamiast tego użyć tagu latest, możesz dodać wywołanie API WithImageTag do łańcucha:

var builder = DistributedApplication.CreateBuilder(args);

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

// Instead of using the "7.4" tag, the "cache" 
// container resource now uses the "latest" tag.

Aby uzyskać więcej informacji oraz zapoznać się z dodatkowymi dostępnymi interfejsami API, zobacz ContainerResourceBuilderExtensions.

Cykl życia zasobu kontenera

Gdy uruchomiony jest host aplikacji, ContainerResource służy do określania, jaki obraz kontenera utworzyć i uruchomić. Pod maską .NET Aspire uruchamia kontener przy użyciu zdefiniowanego obrazu kontenera, delegując wywołania do odpowiedniego środowiska uruchomieniowego kontenera zgodnego ze standardem OCI, Docker lub Podman. Używane są następujące polecenia:

Najpierw kontener jest tworzony przy użyciu polecenia docker container create. Następnie kontener jest uruchamiany przy użyciu polecenia docker container start.

Te polecenia są używane zamiast docker run do zarządzania dołączonymi sieciami kontenerów, woluminami i portami. Wywołanie tych poleceń w tej kolejności umożliwia już obecność dowolnego adresu IP (konfiguracji sieci) podczas początkowego uruchamiania.

Poza podstawowymi typami zasobów ProjectResource, ContainerResourcei ExecutableResource.NET.NET Aspire udostępnia metody rozszerzeń umożliwiające dodawanie typowych zasobów do modelu aplikacji. Aby uzyskać więcej informacji, zobacz Hosting integrations.

Okres istnienia zasobu kontenera

Domyślnie zasoby kontenera używają sesji okresu istnienia kontenera. Oznacza to, że za każdym razem, gdy proces hosta aplikacji jest uruchamiany, kontener jest tworzony i uruchamiany. Po zatrzymaniu hosta aplikacji kontener zostanie zatrzymany i usunięty. Zasoby kontenerów mogą wyrazić zgodę na trwały okres istnienia, aby uniknąć niepotrzebnych ponownych uruchomień i używać stanu utrwalonego kontenera. Aby to osiągnąć, wykonaj sekwencję wywołań interfejsu API ContainerResourceBuilderExtensions.WithLifetime i przekaż ContainerLifetime.Persistent.

var builder = DistributedApplication.CreateBuilder(args);

var ollama = builder.AddContainer("ollama", "ollama/ollama")
    .WithLifetime(ContainerLifetime.Persistent);

Powyższy kod dodaje zasób kontenera o nazwie "ollama" z obrazem "ollama/ollama" i z trwałym czasem istnienia.

Ciąg połączenia i odwołania do punktów końcowych

Często wyraża się zależności między zasobami projektu. Rozważmy następujący przykładowy kod:

var builder = DistributedApplication.CreateBuilder(args);

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

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

builder.AddProject<Projects.AspireApp_Web>("webfrontend")
       .WithReference(cache)
       .WithReference(apiservice);

Odwołania do projektu są obsługiwane inaczej niż zasoby, które mają dobrze zdefiniowane parametry połączenia. Zamiast wstrzykiwać parametry połączenia do zasobu "webfrontend", wstrzykiwane są zmienne środowiskowe do obsługi odkrywania usług.

Metoda Zmienna środowiskowa
WithReference(cache) ConnectionStrings__cache="localhost:62354"
WithReference(apiservice) services__apiservice__http__0="http://localhost:5455"
services__apiservice__https__0="https://localhost:7356"

Dodanie odwołania do projektu "apiservice" powoduje dodanie zmiennych środowiskowych odnajdywania usługi do frontonu. Dzieje się tak, ponieważ zazwyczaj komunikacja między projektami odbywa się za pośrednictwem protokołu HTTP/gRPC. Aby uzyskać więcej informacji, zobacz .NET.NET Aspire odnajdywanie usług.

Aby uzyskać określone punkty końcowe z ContainerResource lub ExecutableResource, użyj jednego z następujących interfejsów API punktu końcowego:

Następnie wywołaj interfejs API GetEndpoint, aby uzyskać punkt końcowy, który może służyć do odwoływania się do punktu końcowego w metodzie WithReference:

var builder = DistributedApplication.CreateBuilder(args);

var customContainer = builder.AddContainer("myapp", "mycustomcontainer")
                             .WithHttpEndpoint(port: 9043, name: "endpoint");

var endpoint = customContainer.GetEndpoint("endpoint");

var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice")
                        .WithReference(endpoint);
Metoda Zmienna środowiskowa
WithReference(endpoint) services__myapp__endpoint__0=https://localhost:9043

Parametr port to port, na który nasłuchuje kontener. Aby uzyskać więcej informacji na temat portów kontenera, zobacz Porty kontenera. Aby uzyskać więcej informacji na temat odnajdywania usług, zobacz .NET.NET Aspire service discovery.

Format zmiennej środowiskowej punktu końcowego usługi

W poprzedniej sekcji metoda WithReference służy do wyrażania zależności między zasobami. Gdy punkty końcowe usługi powodują wstrzyknięcie zmiennych środowiskowych do zasobu zależnego, format może nie być oczywisty. Ta sekcja zawiera szczegółowe informacje na temat tego formatu.

Gdy jeden zasób zależy od innego zasobu, host aplikacji wprowadza zmienne środowiskowe do zasobu zależnego. Te zmienne środowiskowe konfigurują zasób zależny, aby połączył się z zasobem, od którego jest zależny. Format zmiennych środowiskowych jest specyficzny dla .NET.NET Aspire i wyraża punkty końcowe usługi w sposób zgodny z Service Discovery.

Nazwy zmiennych środowiskowych punktu końcowego usługi mają prefiks services__ (podwójne podkreślenie), a następnie nazwę usługi, nazwę punktu końcowego i na koniec indeks. Indeks obsługuje wiele punktów końcowych dla jednej usługi, zaczynając od 0 dla pierwszego punktu końcowego i zwiększając numerację dla każdego kolejnego punktu końcowego.

Rozważmy następujące przykłady zmiennych środowiskowych:

services__apiservice__http__0

Poprzednia zmienna środowiskowa wyraża pierwszy punkt końcowy HTTP dla usługi apiservice. Wartość zmiennej środowiskowej to adres URL punktu końcowego usługi. Nazwany punkt końcowy może być wyrażony w następujący sposób:

services__apiservice__myendpoint__0

W poprzednim przykładzie usługa apiservice ma nazwany punkt końcowy o nazwie myendpoint. Wartość zmiennej środowiskowej to adres URL punktu końcowego usługi.

Odwołuj się do istniejących zasobów

Niektóre sytuacje gwarantują, że odwołujesz się do istniejącego zasobu, być może takiego, który został wdrożony u dostawcy usług w chmurze. Możesz na przykład odwołać się do bazy danych Azure. W takim przypadku należy opierać się na kontekście wykonywania, aby dynamicznie określić, czy host aplikacji jest uruchomiony w trybie "uruchomienia" lub "publikowania". Jeśli korzystasz lokalnie i chcesz polegać na zasobie w chmurze, możesz użyć właściwości IsRunMode, aby warunkowo dodać odwołanie. Zamiast tego możesz utworzyć zasób w trybie publikowania. Niektóre integracje hostingu obsługują bezpośrednie dostarczanie ciągu połączenia, który może służyć do odwoływania się do istniejącego zasobu.

Podobnie mogą wystąpić przypadki użycia, w których chcesz zintegrować .NET.NET Aspire z istniejącym rozwiązaniem. Jednym z typowych podejść jest dodanie projektu hosta aplikacji .NET.NET Aspire do istniejącego rozwiązania. Na hoście aplikacji wyrażasz zależności, dodając odwołania do projektu do hosta aplikacji i rozbudowując model aplikacji. Na przykład jeden projekt może zależeć od innego. Te zależności są wyrażane przy użyciu metody WithReference. Aby uzyskać więcej informacji, zobacz Dodaj .NET Aspire do istniejącej aplikacji .NET.

Cykle życia hosta aplikacji

Host aplikacji .NET.NET Aspire udostępnia kilka cykli życia, do których można się podłączyć, implementując interfejs IDistributedApplicationLifecycleHook. Dostępne są następujące metody cyklu życia:

Zamówienie Metoda Opis
1 BeforeStartAsync Wykonuje się przed uruchomieniem aplikacji rozproszonej.
2 AfterEndpointsAllocatedAsync Wykonuje się po tym, jak orkiestrator przydzieli punkty dostępu dla zasobów w modelu aplikacji.
3 AfterResourcesCreatedAsync Wykonuje się po utworzeniu zasobu przez orchestratora.

Host aplikacji udostępnia haki cyklu życia, ale możesz też chcieć zarejestrować zdarzenia niestandardowe. Aby uzyskać więcej informacji, zobacz Wydarzenia w .NET.NET Aspire.

Zarejestruj mechanizm cyklu życia

Aby zarejestrować hook cyklu życia, zaimplementuj interfejs IDistributedApplicationLifecycleHook i zarejestruj hak w hoście aplikacji przy użyciu interfejsu API AddLifecycleHook.

using Aspire.Hosting.Lifecycle;
using Microsoft.Extensions.Logging;

var builder = DistributedApplication.CreateBuilder(args);

builder.Services.AddLifecycleHook<LifecycleLogger>();

builder.Build().Run();

internal sealed class LifecycleLogger(ILogger<LifecycleLogger> logger)
    : IDistributedApplicationLifecycleHook
{
    public Task BeforeStartAsync(
        DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
    {
        logger.LogInformation("BeforeStartAsync");
        return Task.CompletedTask;
    }

    public Task AfterEndpointsAllocatedAsync(
        DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
    {
        logger.LogInformation("AfterEndpointsAllocatedAsync");
        return Task.CompletedTask;
    }

    public Task AfterResourcesCreatedAsync(
        DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
    {
        logger.LogInformation("AfterResourcesCreatedAsync");
        return Task.CompletedTask;
    }
}

Powyższy kod:

Po uruchomieniu tego hosta aplikacji, hook cyklu życia jest wykonywany dla każdego zdarzenia. Generowane są następujące dane wyjściowe:

info: LifecycleLogger[0]
      BeforeStartAsync
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: LifecycleLogger[0]
      AfterEndpointsAllocatedAsync
info: Aspire.Hosting.DistributedApplication[0]
      Now listening on: https://localhost:17043
info: Aspire.Hosting.DistributedApplication[0]
      Login to the dashboard at https://localhost:17043/login?t=d80f598bc8a64c7ee97328a1cbd55d72
info: LifecycleLogger[0]
      AfterResourcesCreatedAsync
info: Aspire.Hosting.DistributedApplication[0]
      Distributed application started. Press Ctrl+C to shut down.

Preferowanym sposobem integracji z cyklem życia hosta aplikacji jest użycie interfejsu zdarzeń API. Aby uzyskać więcej informacji, zobacz Wydarzenia w .NET.NET Aspire.

Kontekst wykonywania

IDistributedApplicationBuilder udostępnia kontekst wykonywania (DistributedApplicationExecutionContext), który dostarcza informacji o bieżącym wykonaniu hosta aplikacji. Za pomocą tego kontekstu można ocenić, czy host aplikacji wykonuje tryb "uruchom", czy w ramach operacji publikowania. Rozważ następujące właściwości:

  • IsRunMode: zwraca true, jeśli bieżąca operacja jest uruchomiona.
  • IsPublishMode: zwraca true, jeśli bieżąca operacja polega na publikowaniu.

Te informacje mogą być przydatne, gdy chcesz warunkowo wykonać kod na podstawie bieżącej operacji. Rozważmy poniższy przykład, który pokazuje użycie właściwości IsRunMode. W takim przypadku metoda rozszerzająca służy do generowania stabilnej nazwy węzła dla RabbitMQ podczas lokalnych uruchomień deweloperskich.

private static IResourceBuilder<RabbitMQServerResource> RunWithStableNodeName(
    this IResourceBuilder<RabbitMQServerResource> builder)
{
    if (builder.ApplicationBuilder.ExecutionContext.IsRunMode)
    {
        builder.WithEnvironment(context =>
        {
            // Set a stable node name so queue storage is consistent between sessions
            var nodeName = $"{builder.Resource.Name}@localhost";
            context.EnvironmentVariables["RABBITMQ_NODENAME"] = nodeName;
        });
    }

    return builder;
}

Kontekst wykonywania jest często używany do warunkowego dodawania zasobów lub parametrów połączenia wskazujących istniejące zasoby. Rozważmy następujący przykład, który pokazuje warunkowe dodawanie Redis lub parametrów połączenia na podstawie kontekstu wykonywania:

var builder = DistributedApplication.CreateBuilder(args);

var redis = builder.ExecutionContext.IsRunMode
    ? builder.AddRedis("redis")
    : builder.AddConnectionString("redis");

builder.AddProject<Projects.WebApplication>("api")
       .WithReference(redis);

builder.Build().Run();

W poprzednim kodzie:

  • Jeśli host aplikacji jest uruchomiony w trybie "uruchom", zostanie dodany zasób kontenera Redis.
  • Jeśli host aplikacji jest uruchomiony w trybie "publikowania", dodawane są parametry połączenia.

Tę logikę można łatwo przywrócić, aby nawiązać połączenie z istniejącym zasobem Redis podczas uruchamiania lokalnego i utworzyć nowy zasób Redis podczas publikowania.

Ważny

.NET .NET Aspire udostępnia typowe interfejsy API do kontrolowania modalności konstruktorów zasobów, dzięki czemu zasoby zachowują się inaczej na podstawie trybu wykonywania. Płynne interfejsy API są oznaczone RunAs* i PublishAs*. Interfejsy API RunAs* wpływają na zachowanie lokalnego programowania (lub trybu uruchamiania), natomiast interfejsy API PublishAs* wpływają na publikowanie zasobu.

Zobacz też