Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo articolo illustra come personalizzare ulteriormente il comportamento delle risorse scrivendo codice nel progetto AppHost. In Aspireuna risorsa è una parte dipendente di un'applicazione nativa del cloud. I tipi di risorse includono:
- .NET Progetto: un microservizio personalizzato, responsabile di funzionalità specifiche nell'applicazione nativa del cloud e spesso creato da un team separato di sviluppatori.
- Eseguibile: se è necessario compilare microservizi con strumenti come Node.js o Orleans, vengono eseguiti come risorse eseguibili.
- Contenitore: è possibile aggiungere Docker contenitori in base a immagini specifiche per la Aspire soluzione.
- Risorse di integrazione: le integrazioni spesso aggiungono risorse come database, cache e servizi di messaggistica all'applicazione.
- Servizio esterno: rappresenta un'API o un servizio di terze parti da cui dipende l'applicazione ma non è gestita da Aspire. Usare questa opzione per risorse come API pubbliche o endpoint SaaS.
Per informazioni fondamentali sull'orchestrazione Aspire e sul modo in cui gestisce le risorse, vedere Aspire Panoramica dell'orchestrazione.
Convenzioni di denominazione delle risorse
Le risorse in Aspire devono seguire le restrizioni di denominazione impostate da Aspire e la tecnologia rappresentata dalla risorsa. Ad esempio, una Aspire risorsa ha una lunghezza massima di 64 caratteri, ma un'app Azure contenitore ha una lunghezza massima di 32. Quando si pubblica la Aspire risorsa contenitore per Azure, il nome non deve superare i 32 caratteri di lunghezza.
Aspire I nomi delle risorse devono seguire queste regole di base:
- Deve avere una lunghezza compresa tra 1 e 64 caratteri.
- Deve iniziare con una lettera ASCII.
- Deve contenere solo lettere ASCII, cifre e trattini.
- Non deve terminare con un trattino.
- Non deve contenere trattini consecutivi.
Configurare l'esplicito avvio della risorsa
Le risorse di progetto, eseguibile e contenitore vengono avviate automaticamente con l'applicazione distribuita per impostazione predefinita. Una risorsa può essere configurata per attendere un'istruzione di avvio esplicita con il metodo WithExplicitStart. Una risorsa configurata con WithExplicitStart viene inizializzata con KnownResourceStates.NotStarted.
var builder = DistributedApplication.CreateBuilder(args);
var postgres = builder.AddPostgres("postgres");
var postgresdb = postgres.AddDatabase("postgresdb");
builder.AddProject<Projects.AspireApp_DbMigration>("dbmigration")
.WithReference(postgresdb)
.WithExplicitStart();
Nel codice precedente la "dbmigration" risorsa è configurata per non iniziare automaticamente con l'applicazione distribuita.
Le risorse con avvio esplicito possono essere avviate dal Aspire dashboard facendo clic sul comando "Start". Per ulteriori informazioni, consultare il dashboard: Arrestare o avviare una risorsa.
In attesa di risorse
In alcuni casi, potrebbe essere necessario attendere che una risorsa sia pronta prima di avviare un'altra risorsa. Ad esempio, potrebbe essere necessario attendere che un database sia pronto prima di avviare un'API che ne dipende. Per esprimere questa dipendenza, usare il metodo 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);
Nel codice precedente la risorsa di progetto "apiservice" attende che la risorsa di database "postgresdb" entri nello KnownResourceStates.Running stato. Il codice di esempio mostra l'integrazioneAspirePostgreSQL, ma lo stesso modello può essere applicato ad altre risorse.
In alcuni casi potrebbe essere giustificato attendere che una risorsa, KnownResourceStates.Exited o KnownResourceStates.Finished, sia completata prima di avviare la risorsa dipendente. Per attendere il completamento di una risorsa, usare il metodo 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);
Nel codice precedente la risorsa di progetto "apiservice" attende che la risorsa di progetto "migrazione" venga eseguita fino al completamento prima dell'avvio. La risorsa del progetto "migrazione" attende che la risorsa del database "postgresdb" entri nello stato KnownResourceStates.Running. Ciò può essere utile negli scenari in cui si vuole eseguire una migrazione del database prima di avviare il servizio API, ad esempio.
Forzare l'avvio della risorsa nel dashboard
L'attesa di una risorsa può essere ignorata usando il comando Start nel dashboard. Se si seleziona Avvia in una risorsa in attesa nel dashboard, viene indicato di avviarlo immediatamente senza attendere che la risorsa sia integra o completata. Questo può essere utile quando vuoi testare immediatamente una risorsa e non vuoi attendere che l'app sia nello stato corretto.
API per l'aggiunta e l'espressione di risorse
Aspirele integrazioni di hosting e le integrazioni client vengono entrambe distribuite come pacchetti NuGet, ma servono scopi diversi. Mentre le integrazioni client forniscono la configurazione della libreria client per l'utilizzo di app all'esterno dell'ambito di AppHost, le integrazioni di hosting forniscono API per esprimere risorse e dipendenze all'interno di AppHost. Per altre informazioni, vedere Aspire Panoramica delle integrazioni: Responsabilità di integrazione.
Risorse del contenitore "Express"
Per esprimere un ContainerResource, aggiungilo a un'istanza di IDistributedApplicationBuilder tramite il metodo 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");
Per altre informazioni, vedere Supporto GPU in Docker Desktop.
Il codice precedente aggiunge una risorsa container chiamata "ollama" con l'immagine ollama/ollama. La risorsa contenitore è configurata con diversi bind mounts, un endpoint HTTP nominato, un entry point che punta allo script di shell Unix e argomenti di esecuzione del contenitore utilizzando il metodo WithContainerRuntimeArgs.
Personalizzare le risorse del contenitore
Tutte le sottoclassi ContainerResource possono essere personalizzate per soddisfare i requisiti specifici. Può risultare utile quando si utilizza un'integrazione dell'hosting che modella una risorsa di contenitore, ma richiede modifiche. Quando si dispone di un IResourceBuilder<ContainerResource> è possibile concatenare le chiamate a una qualsiasi delle API disponibili per modificare la risorsa contenitore.
Aspire le risorse del contenitore in genere puntano a tag bloccati, ma è possibile usare il tag latest.
Per semplificare questa operazione, si immagini uno scenario in cui si usa l'integrazioneAspireRedis. Se l'integrazione Redis si basa sul tag 7.4 e si vuole usare invece il tag latest, è possibile concatenare una chiamata all'API WithImageTag:
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.
Per altre informazioni e altre API disponibili, vedere ContainerResourceBuilderExtensions.
Ciclo di vita delle risorse del contenitore
Quando viene eseguito AppHost, ContainerResource viene usato per determinare l'immagine del contenitore da creare e avviare. Nel backend, Aspire esegue il contenitore usando l'immagine definita del contenitore delegando le chiamate al runtime del contenitore appropriato e conforme a OCI, Docker o Podman. Vengono usati i comandi seguenti:
Prima di tutto, il contenitore viene creato usando il comando docker container create. Il contenitore viene quindi avviato usando il comando docker container start.
- docker container create: crea un nuovo contenitore dall'immagine specificata, senza avviarlo.
- docker container start: Avvia uno o più contenitori arrestati.
Questi comandi vengono usati invece di docker run per gestire le reti, i volumi e le porte dei contenitori collegati. La chiamata a questi comandi in questo ordine consente a qualsiasi IP (configurazione di rete) di essere già presente all'avvio iniziale.
Oltre ai tipi di risorse di base, ProjectResource, ContainerResourcee ExecutableResource, Aspire fornisce metodi di estensione per aggiungere risorse comuni al modello di app. Per ulteriori informazioni, vedere Integrazioni hosting.
Durata delle risorse del contenitore
Per impostazione predefinita, le risorse del contenitore usano la durata della sessione del contenitore. Ciò significa che ogni volta che viene avviato il processo AppHost, il contenitore viene creato e avviato. Quando AppHost si arresta, il contenitore viene arrestato e rimosso. Le risorse del contenitore possono acconsentire esplicitamente a una durata permanente per evitare riavvii non necessari e usare lo stato del contenitore persistente. A tale scopo, concatenare la chiamata all'API ContainerResourceBuilderExtensions.WithLifetime e passare il parametro ContainerLifetime.Persistent:
var builder = DistributedApplication.CreateBuilder(args);
var ollama = builder.AddContainer("ollama", "ollama/ollama")
.WithLifetime(ContainerLifetime.Persistent);
Il codice precedente aggiunge un contenitore di risorse denominato "ollama" con l'immagine "ollama/ollama" e una durata persistente.
Risorse del servizio esterno Express
I servizi esterni sono API e servizi di terze parti da cui dipende l'applicazione, ma che esistono all'esterno della Aspire soluzione. Questi servizi sono già in esecuzione altrove e non sono gestiti da Aspire. Per esprimere un ExternalServiceResource, lo aggiungi a un'istanza IDistributedApplicationBuilder chiamando il metodo AddExternalService.
var builder = DistributedApplication.CreateBuilder(args);
var nuget = builder.AddExternalService("nuget", "https://api.nuget.org/")
.WithHttpHealthCheck(path: "/v3/index.json");
var frontend = builder.AddProject<Projects.Frontend>("frontend")
.WithReference(nuget);
Il codice precedente aggiunge una risorsa del servizio esterna denominata "nuget" che punta all'API NuGet. Il servizio esterno è configurato con un controllo integrità HTTP per monitorarne la disponibilità. Il progetto front-end può quindi fare riferimento a questo servizio esterno per l'individuazione dei servizi.
I servizi esterni supportano diversi approcci di configurazione:
Configurazione dell'URL statico
È possibile configurare un servizio esterno con un URL statico usando una stringa o un URI:
var builder = DistributedApplication.CreateBuilder(args);
// Using a string URL
var nuget = builder.AddExternalService("nuget", "https://api.nuget.org/");
// Using a URI
var uri = new Uri("https://api.example.com/");
var api = builder.AddExternalService("external-api", uri);
Configurazione dell'URL basata su parametri
Per gli scenari in cui l'URL del servizio esterno può variare tra gli ambienti o deve essere configurabile, è possibile usare i parametri:
var builder = DistributedApplication.CreateBuilder(args);
var externalServiceUrl = builder.AddParameter("external-service-url");
var externalService = builder.AddExternalService("external-service", externalServiceUrl);
var frontend = builder.AddProject<Projects.Frontend>("frontend")
.WithReference(externalService);
Quando si usa la configurazione basata su parametri, il valore dell'URL può essere impostato tramite la configurazione, le variabili di ambiente o i segreti utente. Durante lo sviluppo, Aspire potrebbe richiedere di specificare il valore url. Per altre informazioni, vedere Parametri esterni.
Requisiti dell'URL del servizio esterno
Gli URL dei servizi esterni devono soddisfare requisiti specifici:
- Deve essere un URI assoluto (include schema, host e porta facoltativa).
- Il percorso assoluto deve essere impostato su "/" (nessun segmento di percorso aggiuntivo).
- Non deve contenere parametri di query o frammenti.
Esempi validi:
https://api.example.com/http://localhost:8080/https://service.example.com:9443/
Esempi non validi:
-
https://api.example.com/v1/api(contiene il percorso) -
https://api.example.com/?version=1(contiene query) -
https://api.example.com/#section(contiene frammento di dati)
Controlli di integrità per i servizi esterni
I servizi esterni possono essere configurati con i controlli di integrità HTTP per monitorare la disponibilità:
var builder = DistributedApplication.CreateBuilder(args);
var api = builder.AddExternalService("api", "https://api.example.com/")
.WithHttpHealthCheck(path: "/health", statusCode: 200);
Il WithHttpHealthCheck metodo aggiunge un controllo di integrità che interroga periodicamente il servizio esterno. È possibile specificare:
-
path: percorso relativo per l'endpoint del controllo integrità (facoltativo, per impostazione predefinita non è presente alcun percorso aggiuntivo). -
statusCode: il codice di stato HTTP previsto (facoltativo, il valore predefinito è 200).
Individuazione dei servizi con servizi esterni
Quando si fa riferimento a un servizio esterno da un'altra risorsa, Aspire configura automaticamente l'individuazione del servizio inserendo variabili di ambiente nel formato standard:
var builder = DistributedApplication.CreateBuilder(args);
var api = builder.AddExternalService("api", "https://api.example.com/");
var frontend = builder.AddProject<Projects.Frontend>("frontend")
.WithReference(api);
Questa configurazione inserisce variabili di ambiente come API_HTTPS=https://api.example.com/ e services__api__https__0=https://api.example.com/ nel progetto front-end, abilitando l'individuazione dei servizi tramite meccanismi di individuazione dei servizi semplificati e .NETspecifici.
Ciclo di vita del servizio esterno
I servizi esterni implementano IResourceWithoutLifetime, ovvero non sono gestiti dal sistema del ciclo di vita di Aspire. Dovrebbero essere in esecuzione in modo indipendente. Durante lo sviluppo, i servizi esterni vengono visualizzati nel Aspire dashboard con uno stato "In esecuzione" se sono raggiungibili o mostrano errori di controllo dell'integrità se non sono disponibili.
Relazioni tra risorse
Le relazioni tra risorse collegano le risorse. Le relazioni sono informative e non influiscono sul comportamento di runtime di un'app. Vengono invece usati per visualizzare i dettagli sulle risorse nel dashboard. Ad esempio, le relazioni sono visibili nei dettagli delle risorse del dashboard e Parent le relazioni gestiscono l'annidamento delle risorse nella pagina delle risorse.
Le relazioni vengono create automaticamente da alcune API del modello di app. Per esempio:
-
WithReference aggiunge una relazione alla risorsa di destinazione con il tipo
Reference. -
WaitFor aggiunge una relazione alla risorsa di destinazione con il tipo
WaitFor. - L'aggiunta di un database a un contenitore di database crea una relazione dal database al contenitore con il tipo
Parent.
Le relazioni possono anche essere aggiunte in modo esplicito al modello di app usando WithRelationship e WithParentRelationship.
var builder = DistributedApplication.CreateBuilder(args);
var catalogDb = builder.AddPostgres("postgres")
.WithDataVolume()
.AddDatabase("catalogdb");
builder.AddProject<Projects.AspireApp_CatalogDbMigration>("migration")
.WithReference(catalogDb)
.WithParentRelationship(catalogDb);
builder.Build().Run();
L'esempio precedente usa WithParentRelationship per configurare catalogdb database come padre del progetto migration. La relazione Parent è speciale perché controlla l'annidamento delle risorse nella pagina delle risorse. In questo esempio migration è annidato in catalogdb.
Note
È disponibile la convalida per le relazioni tra risorse padre per impedire a una risorsa di avere più genitori o di creare un riferimento circolare. Non è possibile eseguire il rendering di queste configurazioni nell'interfaccia utente e il modello di app genererà un errore.