Поделиться через


Оркестрация ресурсов в .NET.NET Aspire

В этой статье вы узнаете, как настроить поведение ресурсов дальше, написав код в проекте узла приложения. В .NET.NET Aspireэтом случае ресурс является зависимой частью облачного приложения. Типы ресурсов включают:

  • .NET Проект: пользовательская микрослужба, отвечающая за конкретную функциональность в облачном приложении и часто созданная отдельной командой разработчиков.
  • Выполняемый: Если необходимо создать микрослужбы с инструментами, такими как Node.js или Orleans, они выполняются как исполняемые ресурсы.
  • Контейнер: Вы можете добавлять Docker контейнеры, основанные на конкретных образах, в ваше .NET Aspire решение.
  • Ресурсы интеграции. Интеграция часто добавляет такие ресурсы, как базы данных, кэши и службы обмена сообщениями в приложение.

Основы .NET.NET Aspire оркестрации и управление ресурсами см .NET.NET Aspire . в обзоре оркестрации.

Настройка явного запуска ресурса

Ресурсы проекта, исполняемого файла и контейнера автоматически запускаются с распределенным приложением по умолчанию. Ресурс можно настроить для ожидания явной инструкции запуска с помощью метода WithExplicitStart. Ресурс, настроенный с WithExplicitStart, инициализируется при помощи 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();

В приведенном выше коде ресурс "dbmigration" настроен так, чтобы не запускаться автоматически вместе с распределенным приложением.

Ресурсы с явным началом можно запустить с панели управления .NET.NET Aspire, нажав кнопку "Пуск". Дополнительные сведения см. в разделе .NET.NET Aspire панели мониторинга: остановка или запускресурса.

Ожидание ресурсов

В некоторых случаях может потребоваться ждать, пока ресурс будет готов, прежде чем запускать другой ресурс. Например, вам может потребоваться дождаться готовности базы данных перед запуском API, который зависит от него. Чтобы выразить эту зависимость, используйте метод 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);

В приведенном выше коде ресурс проекта apiservice ожидает, когда ресурс базы данных postgresdb перейдёт в состояние KnownResourceStates.Running. В примере кода показана интеграция .NET AspirePostgreSQL, но к другим ресурсам можно применить тот же шаблон.

В других случаях может потребоваться ожидать завершения ресурса, будь то KnownResourceStates.Exited или KnownResourceStates.Finished, прежде чем зависимый ресурс сможет запуститься. Чтобы ожидать завершения ресурса, используйте метод 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);

В показанном выше коде ресурс проекта "apiservice" ожидает, пока ресурс проекта "миграция" полностью не завершится, прежде чем начать. Ресурс проекта "migration" ожидает, пока ресурс базы данных "postgresdb" войдёт в состояние KnownResourceStates.Running. Это может быть полезно в сценариях, когда необходимо выполнить миграцию базы данных перед запуском службы API, например.

Принудительный запуск ресурсов на панели мониторинга

Ожидание ресурса можно обойти с помощью команды Start на панели управления. При выборе кнопки «Пуск» на панели мониторинга ожидаемому ресурсу даётся команда на немедленный запуск без ожидания его полной готовности или завершения. Это может быть полезно, если вы хотите немедленно протестировать ресурс и не хотите ждать, пока приложение будет находиться в правильном состоянии.

API для добавления и выражения ресурсов

.NET .NET Aspire интеграции хостинга и интеграции с клиентами предоставляются как пакеты NuGet, но они служат разным целям. Хотя интеграции клиентских приложений предоставляют настройку библиотек для использования приложениями за пределами узла приложения, интеграции размещения предоставляют API для выражения ресурсов и зависимостей в пределах узла приложения. Для получения дополнительной информации см. раздел .NET.NET Aspire "Обзор интеграций: Интеграционные обязанности".

Ресурсы контейнера Express

Чтобы выразить ContainerResource, добавьте его в экземпляр IDistributedApplicationBuilder, вызвав метод 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");

Дополнительные сведения см. в разделе поддержка GPU в Docker Desktop.

Предыдущий код добавляет ресурс контейнера с именем "ollama" и изображением ollama/ollama. Ресурс контейнера настраивается с несколькими точками монтирования, с именованной конечной точкой HTTP, точкой входа, которая ссылается на скрипт оболочки Unix, и аргументами запуска контейнера с помощью метода WithContainerRuntimeArgs.

Настройка ресурсов контейнера

Все подклассы ContainerResource можно настроить в соответствии с конкретными требованиями. Это может быть полезно при использовании интеграции хостинга , которая моделирует ресурс контейнера, но требует модификаций. Если у вас есть IResourceBuilder<ContainerResource>, вы можете создавать цепочки вызовов с любым из доступных API и изменять ресурс контейнера. .NET .NET Aspire ресурсы контейнеров обычно указывают на закрепленные теги, но вы можете захотеть использовать тег latest вместо этого.

Чтобы иллюстрировать это, представьте сценарий, в котором вы используете интеграцию .NET AspireRedis. Если интеграция Redis использует тег 7.4 и вы хотите использовать тег latest вместо этого, можно создать цепочку вызовов к 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.

Дополнительные сведения о доступных API см. в ContainerResourceBuilderExtensions.

Жизненный цикл ресурсов контейнера

При запуске хоста приложения ContainerResource используется для определения, какой образ контейнера создать и запустить. Под капотом .NET Aspire запускает контейнер, используя определенный образ контейнера, делегируя вызовы совместимой с OCI среде выполнения контейнеров, либо Docker, либо Podman. Используются следующие команды:

Сначала контейнер создается с помощью команды docker container create. Затем контейнер запускается с помощью команды docker container start.

Эти команды используются вместо docker run для управления подключенными сетями контейнеров, томами и портами. При вызове этих команд в этом порядке любой IP-адрес (конфигурация сети) уже присутствует при первоначальном запуске.

Помимо базовых типов ресурсов, ProjectResource, ContainerResourceи ExecutableResource, .NET.NET Aspire предоставляет методы расширения для добавления общих ресурсов в модель приложения. Дополнительные сведения см. в интеграции хостинга.

Срок службы ресурса контейнера

По умолчанию ресурсы контейнеров используют время жизни контейнера сессии. Это означает, что при каждом запуске процесса узла приложения контейнер создается и запускается. Когда хост приложения останавливается, контейнер останавливается и удаляется. Ресурсы контейнеров могут выбрать постоянное время существования, чтобы избежать ненужных перезапусков и сохранить состояние контейнера. Для этого выполните цепочку вызовов API ContainerResourceBuilderExtensions.WithLifetime и передайте ContainerLifetime.Persistent.

var builder = DistributedApplication.CreateBuilder(args);

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

Предыдущий код добавляет контейнерный ресурс с именем "ollama", используя образ "ollama/ollama" и обеспечивает его постоянное существование.

Связи ресурсов

Связи ресурсов связывают ресурсы. Связи являются информационными и не влияют на поведение среды выполнения приложения. Вместо этого они используются при отображении сведений о ресурсах на панели мониторинга. Например, связи отображаются в сведениях о ресурсах панели мониторинга , а Parent связи управляют вложенностью ресурсов на странице ресурсов.

Связи автоматически создаются некоторыми API модели приложений. Рассмотрим пример.

  • WithReference добавляет связь к целевому ресурсу с типом Reference.
  • WaitFor добавляет связь к целевому ресурсу с типом WaitFor.
  • Добавление базы данных в контейнер базы данных создает связь из базы данных с контейнером с типом Parent.

Связи также можно явно добавить в модель приложения с помощью WithRelationship и 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();

В предыдущем примере используется WithParentRelationship для настройки базы данных catalogdb в качестве родительского проекта migration. Связь Parent является особой, так как она управляет вложением ресурсов на странице ресурса. В этом примере migration находится под catalogdb.

Замечание

Существует проверка родительских связей, чтобы избежать наличия у ресурса нескольких родителей или создания циклической ссылки. Эти конфигурации не могут быть отрисованы в пользовательском интерфейсе, а модель приложения вызовет ошибку.

См. также