Condividi tramite


.NET .NET Aspire panoramica dell'orchestrazione

.NET .NET Aspire fornisce API per esprimere risorse e dipendenze all'interno dell'applicazione distribuita. Oltre a queste API, sono disponibili strumenti che consentono diversi scenari accattivanti. L'orchestratore è progettato per scopi di sviluppo locale e non è supportato per ambienti di produzione.

Prima di continuare, prendere in considerazione una terminologia comune usata in .NET.NET Aspire:

  • Modello di app: raccolta di risorse che costituiscono l'applicazione distribuita (DistributedApplication), definita all'interno dello spazio dei nomi Aspire.Hosting.ApplicationModel. Per una definizione più formale, vedere Definire il modello di app.
  • Progetto App Host/Orchestrator: Il progetto .NET che orchestra il modello di app, denominato con il suffisso *.AppHost (per convenzione).
  • risorsa: una risorsa è una parte dipendente di un'applicazione, ad esempio un progetto .NET, un contenitore, un eseguibile, un database, una cache o un servizio cloud. Rappresenta qualsiasi parte dell'applicazione che può essere gestita o a cui si fa riferimento.
  • Integration: un'integrazione è un pacchetto NuGet per l'host dell'app che modella una risorsa o un pacchetto che configura un client per l'uso in un'app che la utilizza. Per altre informazioni, vedere panoramica delle integrazioni .NET.NET Aspire.
  • riferimento: un riferimento definisce una connessione tra le risorse, espressa come dipendenza usando l'API WithReference. Per altre informazioni, vedere Risorse di riferimento o Fare riferimento alle risorse esistenti.

Nota

.NETL'orchestrazione di.NET Aspireè progettata per migliorare l'esperienza di sviluppo locale semplificando la gestione della configurazione e delle interconnessioni della tua applicazione nativa del cloud. Anche se è uno strumento prezioso per lo sviluppo, non è progettato per sostituire sistemi di ambiente di produzione come Kubernetes, progettati specificamente per eccellere in tale contesto.

Definire il modello di app

.NET .NET Aspire consente di compilare, effettuare il provisioning, distribuire, configurare, testare, eseguire e monitorare le applicazioni distribuite in modo efficiente. Queste funzionalità sono basate su un modello di app, che definisce le risorse nella .NET.NET Aspire soluzione e le relative interconnessioni.

Il modello di app non è solo un elenco di risorse, ma rappresenta la topologia completa dell'applicazione. Sono incluse le relazioni tra le risorse, le relative dipendenze e le relative configurazioni. Le risorse possono includere progetti, eseguibili, contenitori, servizi esterni e risorse cloud su cui si basa l'applicazione.

.NET .NET Aspire Nel progetto host dell'app il file definisce il Program modello di app:

var builder = DistributedApplication.CreateBuilder(args);

// Add resources to the app model

builder.Build().Run();

Quando si chiama DistributedApplication.CreateBuilder, si ottiene un'istanza di IDistributedApplicationBuilder, che viene usata per configurare il modello di app. Questo generatore fornisce metodi per aggiungere risorse, definire le dipendenze e configurare la struttura complessiva dell'applicazione. Dopo aver aggiunto le risorse, chiamare Build per creare il modello di app. I modelli includono codice che concatena una chiamata a Build(), che restituisce un'istanza DistributedApplication e quindi chiama Run().

Progetto di hosting dell'app

Il progetto host dell'app gestisce l'esecuzione di tutti i progetti che fanno parte del progetto .NET.NET Aspire. In altre parole, è responsabile dell'orchestrazione di tutte le app all'interno del modello di app. Il progetto stesso è un progetto eseguibile .NET che fa riferimento al pacchetto NuGet 📦Aspire.Hosting.AppHost e utilizza l'SDK .NET.NET Aspire:

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

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

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

    <!-- Omitted for brevity -->

</Project>

Il codice seguente descrive un host dell'app Program con due riferimenti al progetto e una cache 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();

Il codice precedente:

  • Crea un nuovo generatore di modelli di app usando il metodo CreateBuilder.
  • Aggiunge una risorsa Rediscache denominata "cache" usando il metodo AddRedis.
  • Aggiunge una risorsa di progetto denominata "apiservice" usando il metodo AddProject.
  • Aggiunge una risorsa di progetto denominata "webfrontend" usando il metodo AddProject.
    • Specifica che il progetto dispone di endpoint HTTP esterni usando il metodo WithExternalHttpEndpoints.
    • Aggiunge un riferimento alla risorsa cache e attende che sia pronto usando i metodi WithReference e WaitFor.
    • Aggiunge un riferimento alla risorsa apiservice e attende che sia pronto usando i metodi WithReference e WaitFor.
  • Compila ed esegue il modello di app usando i metodi Build e Run.

Il codice di esempio usa .NET AspireRedis l'integrazione dell'hosting.

Per visualizzare la relazione tra il progetto host dell'app e le risorse descritte, considerare il diagramma seguente:

La relazione tra i progetti nel modello di applicazione iniziale di .NET.NET Aspire.

Ogni risorsa deve essere denominata in modo univoco. Questo diagramma mostra ogni risorsa e le relazioni tra di esse. La risorsa contenitore è denominata "cache" e le risorse del progetto sono denominate "apiservice" e "webfrontend". Il progetto front-end Web fa riferimento ai progetti della cache e del servizio API. Quando si esprimono riferimenti in questo modo, il progetto frontend web dichiara che dipende rispettivamente da queste due risorse: la "cache" e "apiservice".

Tipi di risorse predefiniti

I progetti .NETe.NET Aspire sono costituiti da un insieme di risorse. Tipi primari di risorse di base nel pacchetto NuGet 📦Aspire.Hosting.AppHost sono descritti nella tabella seguente.

Metodo Tipo di risorsa Descrizione
AddProject ProjectResource Un progetto .NET, ad esempio un'app Web ASP.NET Core.
AddContainer ContainerResource Immagine del contenitore, ad esempio un'immagine Docker.
AddExecutable ExecutableResource Un file eseguibile, ad esempio un'app Node.js.
AddParameter ParameterResource Risorsa di parametro che può essere usata per esprimere i parametri esterni.

Le risorse del progetto rappresentano .NET progetti che fanno parte del modello di app. Quando si aggiunge un riferimento al progetto host dell'app, .NET.NET Aspire SDK genera un tipo nello spazio dei nomi Projects per ogni progetto a cui si fa riferimento. Per altre informazioni, vedere .NET.NET Aspire SDK: Riferimenti ai progetti.

Per aggiungere un progetto al modello di app, usare il metodo AddProject:

var builder = DistributedApplication.CreateBuilder(args);

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

I progetti possono essere replicati e ridimensionati aggiungendo più istanze dello stesso progetto al modello di app. Per configurare le repliche, usare il metodo 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);

Il codice precedente aggiunge tre repliche della risorsa di progetto "apiservice" al modello di app. Per altre informazioni, vedere dashboard .NET.NET Aspire: Repliche di risorse.

Risorse di riferimento

Un riferimento rappresenta una dipendenza tra le risorse. Ad esempio, è possibile immaginare uno scenario in cui un front-end Web dipende da una Redis cache. Si consideri il seguente host di esempio dell'app, codice C# Program:

var builder = DistributedApplication.CreateBuilder(args);

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

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

La risorsa di progetto "webfrontend" usa WithReference per aggiungere una dipendenza dalla risorsa contenitore "cache". Queste dipendenze possono rappresentare stringhe di connessione o informazioni sull'individuazione dei servizi. Nell'esempio precedente una variabile di ambiente viene inserita nella risorsa "webfrontend" con il nome ConnectionStrings__cache. Questa variabile di ambiente contiene una stringa di connessione usata dal webfrontend per connettersi a Redis tramite l'integrazione .NET AspireRedis, ad esempio ConnectionStrings__cache="localhost:62354".

Riferimenti alle stringhe di connessione e agli endpoint

È comune esprimere le dipendenze tra le risorse del progetto. Si consideri il codice di esempio seguente:

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

I riferimenti da progetto a progetto vengono gestiti in modo diverso rispetto alle risorse con stringhe di connessione ben definite. Anziché inserire la stringa di connessione nella risorsa "webfrontend", le variabili di ambiente per supportare l'individuazione del servizio vengono inserite.

Metodo Variabile di ambiente
WithReference(cache) ConnectionStrings__cache="localhost:62354"
WithReference(apiservice) services__apiservice__http__0="http://localhost:5455"
services__apiservice__https__0="https://localhost:7356"

L'aggiunta di un riferimento al progetto "apiservice" comporta l'aggiunta di variabili di ambiente di individuazione dei servizi al front-end. Ciò è dovuto al fatto che, in genere, la comunicazione da progetto a progetto avviene tramite HTTP/gRPC. Per ulteriori informazioni, vedere .NET.NET Aspireindividuazione del servizio.

Per ottenere endpoint specifici da un ContainerResource o da un ExecutableResource, usare una delle API endpoint seguenti:

Chiamare quindi l'API GetEndpoint per ottenere l'endpoint che può essere usato per fare riferimento all'endpoint nel metodo 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);
Metodo Variabile di ambiente
WithReference(endpoint) services__myapp__endpoint__0=https://localhost:9043

Il parametro port è la porta su cui il contenitore è in ascolto. Per ulteriori informazioni sui porti per container, vedere Porti per container. Per ulteriori informazioni sull'individuazione del servizio, vedere .NET.NET Aspire individuazione del servizio.

Formato della variabile di ambiente dell'endpoint di servizio

Nella sezione precedente il metodo WithReference viene usato per esprimere le dipendenze tra le risorse. Quando gli endpoint di servizio comportano l'inserimento di variabili di ambiente nella risorsa dipendente, il formato potrebbe non essere ovvio. Questa sezione fornisce informazioni dettagliate su questo formato.

Quando una risorsa dipende da un'altra risorsa, l'host dell'app inserisce le variabili di ambiente nella risorsa dipendente. Queste variabili di ambiente configurano la risorsa dipendente per connettersi alla risorsa dalla quale dipende. Il formato delle variabili di ambiente è specifico per .NET.NET Aspire ed esprime gli endpoint di servizio in modo compatibile con Individuazione servizi.

I nomi delle variabili di ambiente dell'endpoint di servizio hanno il prefisso services__ (doppio carattere di sottolineatura), quindi il nome del servizio, il nome dell'endpoint e infine l'indice. L'indice supporta più endpoint per un singolo servizio, a partire da 0 per il primo endpoint e incrementando per ciascun endpoint successivo.

Si considerino gli esempi di variabili di ambiente seguenti:

services__apiservice__http__0

La variabile di ambiente precedente esprime il primo endpoint HTTP per il servizio apiservice. Il valore della variabile di ambiente è l'URL dell'endpoint di servizio. Un endpoint denominato può essere espresso nel modo seguente:

services__apiservice__myendpoint__0

Nell'esempio precedente il servizio apiservice ha un endpoint denominato myendpoint. Il valore della variabile di ambiente è l'URL dell'endpoint di servizio.

Fare riferimento alle risorse esistenti

Alcune situazioni garantiscono di fare riferimento a una risorsa esistente, ad esempio una risorsa distribuita in un provider di servizi cloud. Ad esempio, è possibile fare riferimento a un database Azure. In questo caso, si fa affidamento sul contesto di esecuzione per determinare in modo dinamico se l'host dell'app è in esecuzione in modalità "run" o "publish". Se si esegue localmente e si vuole basarsi su una risorsa cloud, è possibile usare la proprietà IsRunMode per aggiungere in modo condizionale il riferimento. È possibile scegliere di creare la risorsa in modalità di pubblicazione. Alcune integrazioni di hosting supportano direttamente la fornitura di una stringa di connessione, che può essere usata per fare riferimento a una risorsa esistente.

Analogamente, potrebbero esserci casi d'uso in cui si vuole integrare .NET.NET Aspire in una soluzione esistente. Un approccio comune consiste nell'aggiungere il progetto host dell'applicazione .NET.NET Aspire a una soluzione esistente. All'interno dell'host dell'app, è possibile esprimere le dipendenze aggiungendo riferimenti di progetto all'host dell'app e costruendo il modello dell'app. Ad esempio, un progetto potrebbe dipendere da un altro. Queste dipendenze vengono espresse usando il metodo WithReference. Per altre informazioni, vedere Aggiungere .NET Aspire a un'app .NET esistente.

Contesto di esecuzione

Il IDistributedApplicationBuilder espone un contesto di esecuzione (DistributedApplicationExecutionContext), che fornisce informazioni sull'esecuzione corrente dell'host dell'applicazione. Questo contesto può essere usato per valutare se l'host dell'app è in esecuzione in modalità "run" o come parte di un'operazione di pubblicazione. Si considerino le proprietà seguenti:

  • IsRunMode: restituisce true se l'operazione corrente è in esecuzione.
  • IsPublishMode: restituisce true se l'operazione corrente è pubblicazione.

Queste informazioni possono essere utili quando si vuole eseguire codice in modo condizionale in base all'operazione corrente. Si consideri l'esempio seguente che illustra l'uso della proprietà IsRunMode. In questo caso, viene usato un metodo di estensione per generare un nome di nodo stabile per RabbitMQ per le esecuzioni di sviluppo locale.

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

Il contesto di esecuzione viene spesso usato per aggiungere in modo condizionale risorse o stringhe di connessione che puntano alle risorse esistenti. Si consideri l'esempio seguente che illustra l'aggiunta condizionale di Redis o una stringa di connessione in base al contesto di esecuzione:

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

Nel codice precedente:

  • Se l'host dell'app è in modalità "run", viene aggiunta una Redis risorsa contenitore.
  • Se l'host dell'app è in modalità di pubblicazione, viene aggiunta una stringa di connessione.

Questa logica può essere facilmente invertita per connettersi a una risorsa di Redis esistente quando si esegue localmente e creare una nuova risorsa Redis durante la pubblicazione.

Importante

.NET .NET Aspire fornisce API comuni per controllare la modalità dei generatori di risorse, consentendo alle risorse di comportarsi in modo diverso in base alla modalità di esecuzione. Le API Fluent sono precedute da RunAs* e PublishAs*. Le API RunAs* influenzano il comportamento di sviluppo locale (o modalità di esecuzione), mentre le API PublishAs* influenzano la pubblicazione della risorsa. Per altre informazioni su come le risorse di Azure usano queste API, vedere Usare le risorse di Azure esistenti.

Vedere anche