Compartir a través de


Orquestación de recursos en .NET.NET Aspire

En este artículo, aprenderá a personalizar aún más el comportamiento de los recursos escribiendo código en el proyecto host de la aplicación. En .NET.NET Aspire, un recurso es una parte dependiente de una aplicación nativa de nube. Los tipos de recursos incluyen:

  • .NET Proyecto: un microservicio personalizado, responsable de una funcionalidad específica en la aplicación nativa de la nube y, a menudo, compilado por un equipo independiente de desarrolladores.
  • Ejecutable: si necesita compilar microservicios con herramientas como Node.js o Orleans, se ejecutan como recursos ejecutables.
  • Contenedor: puedes agregar Docker contenedores, basados en imágenes específicas a tu .NET Aspire solución.
  • Recursos de integración: las integraciones suelen agregar recursos como bases de datos, cachés y servicios de mensajería a la aplicación.

Para conocer los aspectos básicos de .NET.NET Aspire la orquestación y cómo administra los recursos, consulte .NET.NET Aspire introducción a la orquestación.

Convenciones de nomenclatura de recursos

Los recursos de .NET Aspire deben seguir las restricciones de nomenclatura establecidas por .NET Aspire y la tecnología que representa el recurso. Por ejemplo, un .NET Aspire recurso tiene una longitud máxima de nombre de 64 caracteres, pero una Azure aplicación contenedora tiene una longitud máxima de 32. Al publicar el recurso de .NET Aspire contenedor para Azure, el nombre no debe superar los 32 caracteres de longitud.

.NET .NET Aspire Los nombres de recursos deben seguir estas reglas básicas:

  • Debe tener entre 1 y 64 caracteres de longitud.
  • Debe comenzar con una letra ASCII.
  • Debe contener solo letras ASCII, dígitos y guiones.
  • No debe terminar con un guión.
  • No debe contener guiones consecutivos.

Configura el inicio explícito de recursos

Los recursos de proyecto, ejecutable y contenedor se inician automáticamente con la aplicación distribuida de forma predeterminada. Se puede configurar un recurso para esperar una instrucción de inicio explícita con el método WithExplicitStart. Un recurso configurado con WithExplicitStart se inicializa 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();

En el código anterior, el "dbmigration" recurso está configurado para que no se inicie automáticamente con la aplicación distribuida.

Los recursos con inicio explícito se pueden iniciar desde el panel de .NET.NET Aspire haciendo clic en el comando "Iniciar". Para obtener más información, consulte .NET.NET Aspire panel: Detener o Iniciar un recurso.

Esperando recursos

En algunos casos, es posible que quiera esperar a que un recurso esté listo antes de iniciar otro recurso. Por ejemplo, es posible que quiera esperar a que una base de datos esté lista antes de iniciar una API que dependa de ella. Para expresar esta dependencia, use el método 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);

En el código anterior, el recurso del proyecto "apiservice" espera que el recurso de base de datos "postgresdb" entre en estado KnownResourceStates.Running . El código de ejemplo muestra la .NET AspirePostgreSQL integración, pero el mismo patrón se puede aplicar a otros recursos.

Otros casos pueden justificar la espera de que un recurso se ejecute hasta su finalización, ya sea KnownResourceStates.Exited o KnownResourceStates.Finished antes de que se inicie el recurso dependiente. Para esperar a que un recurso se ejecute hasta su finalización, use el método 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);

En el código anterior, el recurso de proyecto "apiservice" espera a que el recurso de proyecto "migration" se complete antes de comenzar. El recurso del proyecto "migration" espera a que el recurso de base de datos "postgresdb" entre al estado KnownResourceStates.Running. Esto puede ser útil en escenarios en los que desea ejecutar una migración de base de datos antes de iniciar el servicio de API, por ejemplo.

Forzar el inicio de recursos en el panel de control

Se puede omitir la espera de un recurso mediante el comando Iniciar en el panel. Al seleccionar Iniciar en un recurso en espera en el panel, se indica que se inicie inmediatamente sin esperar a que el recurso esté en buen estado o completado. Esto puede ser útil cuando desea probar un recurso inmediatamente y no desea esperar a que la aplicación esté en el estado correcto.

API para agregar y expresar recursos

.NET .NET Aspire Las integraciones de hospedaje y las integraciones de cliente se entregan como paquetes NuGet, pero sirven para fines diferentes. Aunque las integraciones de cliente proporcionan configuración de biblioteca cliente para consumir aplicaciones fuera del ámbito del host de la aplicación, las integraciones de hospedaje proporcionan API para expresar recursos y dependencias dentro del host de la aplicación. Para obtener más información, consulte .NET.NET Aspire Integrations overview: Integration responsibilities (Información general sobre las integraciones: Responsabilidades de integración).

Recursos de contenedor expreso

Para expresar un ContainerResource, debes agregarlo a una instancia de IDistributedApplicationBuilder llamando al método 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");

Para obtener más información, consulte Compatibilidad con GPU en Docker escritorio.

El código anterior agrega un recurso de contenedor denominado "ollama" con la imagen ollama/ollama. El recurso de contenedor está configurado con varios montajes de unión, un punto de conexión HTTP nombrado, un punto de entrada que se resuelve en un guion de shell Unix y argumentos para la ejecución del contenedor con el método WithContainerRuntimeArgs.

Personalización de recursos de contenedor

Todas las ContainerResource subclases se pueden personalizar para satisfacer sus requisitos específicos. Esto puede ser útil al usar una integración de hospedaje que modele un recurso de contenedor, pero requiere modificaciones. Cuando tenga un IResourceBuilder<ContainerResource> puede encadenar llamadas a cualquiera de las API disponibles para modificar el recurso de contenedor. Los recursos de contenedor .NET.NET Aspire suelen apuntar a etiquetas ancladas, pero podría preferir usar la etiqueta latest en su lugar.

Para ayudar a ejemplificar esto, imagina un escenario donde estás usando la .NET AspireRedis integración. Si la integración de Redis se basa en la etiqueta 7.4 y quiere usar la etiqueta latest en su lugar, puede encadenar una llamada a la API de 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.

Para obtener más información y otras API disponibles, consulte ContainerResourceBuilderExtensions.

Ciclo de vida de los recursos del contenedor

Cuando se ejecuta el host de la aplicación, el ContainerResource se usa para determinar qué imagen de contenedor se va a crear e iniciar. En segundo plano, .NET Aspire ejecuta el contenedor utilizando la imagen de contenedor definida al delegar llamadas al entorno de ejecución de contenedores compatible con OCI apropiado, ya sea Docker o Podman. Se usan los siguientes comandos:

En primer lugar, el contenedor se crea con el comando docker container create. A continuación, el contenedor se inicia mediante el comando docker container start.

Estos comandos se usan en lugar de docker run para administrar redes, volúmenes y puertos de contenedor conectados. Llamar a estos comandos en este orden permite que cualquier dirección IP (configuración de red) ya esté presente en el inicio inicial.

Además de los tipos de recursos base, ProjectResource, ContainerResourcey ExecutableResource, .NET.NET Aspire proporciona métodos de extensión para agregar recursos comunes al modelo de aplicación. Para obtener más información, consulte Hospedaje de integraciones.

Duración de los recursos del contenedor

De forma predeterminada, los recursos de contenedor usan la vida útil del contenedor de sesión. Esto significa que cada vez que se inicia el proceso de host de la aplicación, se crea e inicia el contenedor. Cuando se detiene el host de la aplicación, el contenedor se detiene y se elimina. Los recursos de los contenedores pueden optar por una vida útil persistente para evitar reinicios innecesarios y utilizar el estado persistente del contenedor. Para lograrlo, encadena una llamada a la API ContainerResourceBuilderExtensions.WithLifetime y pasa ContainerLifetime.Persistent

var builder = DistributedApplication.CreateBuilder(args);

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

El código anterior agrega un recurso de contenedor denominado "ollama" con la imagen "ollama/ollama" y una duración persistente.

Relaciones de recursos

Las relaciones de recursos vinculan los recursos juntos. Las relaciones son informativas y no afectan al comportamiento en tiempo de ejecución de una aplicación. En su lugar, se usan al mostrar detalles sobre los recursos en el panel. Por ejemplo, las relaciones son visibles en los detalles de recursos del panel de control , y las relaciones de Parent controlan el anidamiento de recursos en la página de recursos.

Algunas API de modelo de aplicación crean automáticamente relaciones. Por ejemplo:

  • WithReference agrega una relación al recurso de destino con el tipo Reference.
  • WaitFor agrega una relación al recurso de destino con el tipo WaitFor.
  • Al agregar una base de datos a un contenedor de base de datos, se crea una relación desde la base de datos al contenedor con el tipo Parent.

Las relaciones también se pueden agregar explícitamente al modelo de aplicación mediante WithRelationship y 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();

En el ejemplo anterior se usa WithParentRelationship para configurar la base de datos catalogdb como elemento primario del proyecto migration. La relación Parent es especial porque controla el anidamiento de recursos en la página de recursos. En este ejemplo, migration está anidado en catalogdb.

Nota:

Hay validación para las relaciones de padre para evitar que un recurso tenga múltiples padres o cree una referencia circular. Estas configuraciones no se pueden representar en la interfaz de usuario y el modelo de aplicación producirá un error.

Consulte también