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


Обзор оркестрации .NET.NET Aspire

.NET .NET Aspire предоставляет API для выражения ресурсов и зависимостей в распределенном приложении. В дополнение к этим API есть инструменты, которые обеспечивают несколько убедительных сценариев. Оркестратор предназначен для целей локальной разработки и не поддерживается в производственных средах.

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

  • модель приложений: коллекция ресурсов, составляющих распределенное приложение (DistributedApplication), определенное в пространстве имен Aspire.Hosting.ApplicationModel. Более формальное определение см. в разделе Определение модели приложения.
  • Хост приложения/проект Orchestrator: проект .NET, который оркестрирует модель приложения, названный с суффиксом *.AppHost (по договоренности).
  • ресурс: ресурс является зависимой частью приложения, например проекта .NET, контейнера, исполняемого файла, базы данных, кэша или облачной службы. Он представляет любую часть приложения, которую можно управлять или ссылаться.
  • Интеграция: Интеграция — это пакет NuGet для узла приложения, который моделирует ресурс, или пакет, который настраивает клиент для использования в приложении-получателе. Дополнительные сведения см. в обзоре интеграции .NET.NET Aspire.
  • Ссылка: Ссылка определяет соединение между ресурсами, выраженное как зависимость с помощью API WithReference. Дополнительные сведения см. в статье Справочные ресурсы или Ссылки на существующие ресурсы.

Заметка

оркестрация .NET.NET Aspireразработана для того, чтобы улучшить ваш опыт локальной разработки, упростив управление конфигурацией и взаимодействиями вашего облачно-ориентированного приложения. Хотя это бесценный инструмент для разработки, он не предназначен для замены систем рабочей среды, таких как Kubernetes, которые специально созданы, чтобы превосходно работать в этом контексте.

Определение модели приложения

.NET .NET Aspire позволяет эффективно создавать, подготавливать, развертывать, настраивать, тестировать, запускать и отслеживать распределенные приложения. Эти возможности поддерживаются моделью приложения, которая определяет ресурсы в .NET.NET Aspire решении и их взаимодействия.

Модель приложения — это не просто список ресурсов, который представляет полную топологию приложения. К ним относятся связи между ресурсами, их зависимостями и их конфигурациями. Ресурсы могут включать проекты, исполняемые файлы, контейнеры, внешние службы и облачные ресурсы, на которые используется ваше приложение.

.NET .NET Aspire В проекте узла приложения файл Program определяет модель приложения:

var builder = DistributedApplication.CreateBuilder(args);

// Add resources to the app model

builder.Build().Run();

При вызове DistributedApplication.CreateBuilderвы получите экземпляр IDistributedApplicationBuilder, который используется для настройки модели приложения. Этот построитель предоставляет методы для добавления ресурсов, определения зависимостей и настройки общей структуры приложения. После добавления ресурсов вызовите Build, чтобы создать модель приложения. Шаблоны включают код, который связывает вызов Build(), возвращающий экземпляр DistributedApplication, а затем вызывает Run().

Проект хоста приложения

Проект узла приложения управляет выполнением всех проектов, которые входят в состав единого проекта .NET.NET Aspire. Другими словами, она отвечает за оркестрацию всех приложений в модели приложения. Сам проект — это исполняемый .NET проект, который ссылается на пакет NuGet 📦Aspire.Hosting.AppHost и использует .NET.NET Aspire SDK:

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

Следующий код описывает хост приложения Program с двумя ссылками на проект, а также кэшем 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();

Предыдущий код:

  • Создает конструктор модели приложения, используя метод CreateBuilder.
  • Добавляет Rediscache ресурс с именем cache с помощью метода AddRedis.
  • Добавляет ресурс проекта с именем apiservice с помощью метода AddProject.
  • Добавляет ресурс проекта с именем webfrontend с помощью метода AddProject.
    • Указывает, что проект имеет внешние конечные точки HTTP с помощью метода WithExternalHttpEndpoints.
    • Добавляет ссылку на ресурс cache и ожидает его готовности с помощью методов WithReference и WaitFor.
    • Добавляет ссылку на ресурс apiservice и ожидает его готовности с помощью методов WithReference и WaitFor.
  • Создает и запускает модель приложения с помощью методов Build и Run.

В примере кода используется .NET AspireRedis хостинговая интеграция.

Чтобы визуализировать связь между проектом узла приложения и описанными ресурсами, рассмотрим следующую схему:

Связь между проектами в шаблоне начального приложения .NET.NET Aspire.

Каждый ресурс должен иметь уникальное имя. На этой схеме показаны все ресурсы и связи между ними. Ресурс контейнера называется cache, а ресурсы проекта называются apiservice и webfrontend. Проект веб-интерфейса ссылается на проекты кэша и службы API. Когда вы выражаете ссылки таким образом, проект веб-интерфейса говорит, что он зависит от этих двух ресурсов — "кэш" и "api-сервис" соответственно.

Встроенные типы ресурсов

.NET .NET Aspire проекты состоят из набора ресурсов. Базовые типы ресурсов в 📦Aspire.Hosting.AppHost пакета NuGet описаны в следующей таблице.

Метод Тип ресурса Описание
AddProject ProjectResource Проект .NET, например, ASP.NET Core веб-приложение.
AddContainer ContainerResource Образ контейнера, например образ Docker.
AddExecutable ExecutableResource Исполняемый файл, например Node.js приложение.
AddParameter ParameterResource Ресурс параметра, который можно использовать для выражения внешних параметров.

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

Чтобы добавить проект в модель приложения, используйте метод AddProject:

var builder = DistributedApplication.CreateBuilder(args);

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

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

Приведенный выше код добавляет три реплики ресурса проекта apiservice в модель приложения. Дополнительные сведения см. на панели мониторинга .NET.NET Aspire: реплики ресурсов.

Справочные ресурсы

Ссылка обозначает зависимость между ресурсами. Например, можно представить сценарий, в котором веб-интерфейс зависит от кэша Redis . Рассмотрим следующий пример кода узла приложения Program C#:

var builder = DistributedApplication.CreateBuilder(args);

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

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

Ресурс проекта "webfrontend" использует WithReference для добавления зависимости от ресурса контейнера "cache". Эти зависимости могут представлять строки подключения или сведения об обнаружении служб. В предыдущем примере переменная среды внедрена в ресурс webfrontend с именем ConnectionStrings__cache. Эта переменная среды содержит строку подключения, которую webfrontend использует для подключения к Redis через интеграцию .NET AspireRedis, например, ConnectionStrings__cache="localhost:62354".

Ссылки на строку подключения и конечную точку

Обычно выражают зависимости между ресурсами проекта. Рассмотрим следующий пример кода:

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

Ссылки между проектами обрабатываются иначе, чем ресурсы с четко определёнными строками подключения. Вместо внедрения строки подключения в ресурс "webfrontend" внедряются переменные среды, поддерживающие обнаружение служб.

Метод Переменная среды
WithReference(cache) ConnectionStrings__cache="localhost:62354"
WithReference(apiservice) services__apiservice__http__0="http://localhost:5455"
services__apiservice__https__0="https://localhost:7356"

Добавление ссылки на проект apiservice приводит к добавлению переменных среды обнаружения служб в интерфейсную часть. Это связано с тем, что обычно обмен данными между проектами происходит по протоколу HTTP/gRPC. Дополнительные сведения см. в .NET.NET Aspire разделе «Обнаружение служб».

Чтобы получить определенные конечные точки из ContainerResource или ExecutableResource, используйте один из следующих API конечных точек:

Затем вызовите API GetEndpoint, чтобы получить конечную точку, которую можно использовать для ссылки на конечную точку в методе 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);
Метод Переменная среды
WithReference(endpoint) services__myapp__endpoint__0=https://localhost:9043

Параметр port — это порт, который прослушивается контейнером. Дополнительную информацию о контейнерных портах см. в Порты контейнеров. Для получения дополнительной информации об обнаружении служб см. обнаружение служб.NET.NET Aspire.

Формат переменной среды конечной точки службы

В предыдущем разделе метод WithReference используется для выражения зависимостей между ресурсами. Если конечные точки службы приводят к внедрению переменных среды в зависимый ресурс, формат может не быть очевидным. В этом разделе содержатся сведения об этом формате.

Если один ресурс зависит от другого ресурса, узел приложения внедряет переменные среды в зависимый ресурс. Эти переменные среды настраивают зависимый ресурс для подключения к ресурсу, от которого он зависит. Формат переменных среды зависит от .NET.NET Aspire и задаёт конечные точки службы в формате, совместимом с Service Discovery.

Имена переменных среды конечной точки службы префиксируются с помощью services__ (двойного подчеркивания), а затем имя службы, имя конечной точки и, наконец, индекс. Индекс поддерживает несколько конечных точек для одной службы, начиная с 0 для первой точки и увеличивая на один для каждой следующей точки.

Рассмотрим следующие примеры переменных среды:

services__apiservice__http__0

Предыдущая переменная среды выражает первую конечную точку HTTP для службы apiservice. Значение переменной среды — URL-адрес конечной точки службы. Именованная конечная точка может быть выражена следующим образом:

services__apiservice__myendpoint__0

В предыдущем примере служба apiservice имеет именованную конечную точку с именем myendpoint. Значение переменной среды — URL-адрес конечной точки службы.

Ссылка на существующие ресурсы

Некоторые ситуации предполагают, что вы ссылаетесь на существующий ресурс, возможно, тот, который развернут у облачного провайдера. Например, может потребоваться ссылаться на базу данных Azure. В этом случае вы будете полагаться на Контекст выполнения для динамического определения того, работает ли хост приложения в режиме "run" или в режиме "publish". Если вы работаете локально и хотите использовать облачный ресурс, можно использовать свойство IsRunMode для условного добавления ссылки. Вместо этого можно создать ресурс в режиме публикации. Некоторые интеграции хостинга поддерживают предоставление строки подключения непосредственно, которую можно использовать для обращения к существующему ресурсу.

Аналогичным образом, могут возникнуть случаи, когда требуется интегрировать .NET.NET Aspire в существующее решение. Одним из распространенных подходов является добавление проекта хостинга приложений .NET.NET Aspire в существующее решение. В узле приложения вы выражаете зависимости, добавляя ссылки на проекты в узел приложения и сборку модели приложения. Например, один проект может зависеть от другого. Эти зависимости выражаются с помощью метода WithReference. Дополнительные сведения см. в статье Добавление .NET Aspire в существующее приложение .NET.

Контекст выполнения

IDistributedApplicationBuilder предоставляет контекст выполнения (DistributedApplicationExecutionContext), который подаёт сведения о текущем выполнении хоста приложения. Этот "контекст" можно использовать для оценки того, выполняется ли хост приложения в режиме "выполнения" или как часть операции публикации. Рассмотрим следующие свойства:

  • IsRunMode: возвращает true, если выполняется текущая операция.
  • IsPublishMode: возвращает true, если текущая операция — публикация.

Эти сведения могут быть полезны, если вы хотите условно выполнить код на основе текущей операции. Рассмотрим следующий пример, демонстрирующий использование свойства IsRunMode. В этом случае метод расширения используется для создания стабильного имени узла для RabbitMQ для локальных запусков разработки.

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

Контекст выполнения часто используется для условного добавления ресурсов или строк подключения, указывающих на существующие ресурсы. Рассмотрим следующий пример, демонстрирующий условное добавление Redis или строки подключения на основе контекста выполнения:

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

В приведенном выше коде:

  • Если узел приложения находится в режиме "выполнения", добавляется ресурс контейнера Redis.
  • Если узел приложения находится в «режиме публикации», добавляется строка подключения.

Эта логика может быть легко перевернута для подключения к существующему ресурсу Redis при локальном запуске и создании нового ресурса Redis при публикации.

Важный

.NET .NET Aspire предоставляет общие API для управления модальность конструкторов ресурсов, что позволяет ресурсам вести себя по-разному в зависимости от режима выполнения. Интерфейсы API fluent имеют префикс RunAs* и PublishAs*. API RunAs* влияют на поведение локальной разработки (или режима выполнения), а API PublishAs* влияют на публикацию ресурса. Дополнительные сведения о том, как ресурсы Azure используют эти API, см. в статье Использование существующих ресурсов Azure.

См. также