Обзор .NET Aspire
Что такое Aspire?
.NET Aspire - стек для создания resilient, observable, и configurable cloud-native приложух на базе C#. Он включает в себя набор компонентов, улучшенных для cloud-native, в том числе service discovery, telemetry, resilience, и health-check по умолчанию. Aspire позволяет настраивать необходимые зависимости для cloud-native приложений для новых и существующих приложений .NET, использующих .NET 8+.
Документацию можно найти по ссылках: Docs, GitHub.
Обзор Aspire
Visual Studio Solution
Если создать приложение с помощью темплейта в VS studio:
Вы увидите два новых проекта, которых раньше не было <appname>.AppHost
и <appname>.ServiceDefaults
.
В проекте AppHost
будут запущены все проекты .NET, контейнеры и исполняемые файлы, необходимые для создания распределенного приложения.
Проект ServiceDefaults
содержит общую логику, ориентированную на сервисы, которая применяется ко всем проектам в приложении. Здесь настраиваются такие сквозные задачи, как service discovery, телеметрия и helth-check endpoint'ы. Microsoft хотели, чтобы эти настройки были единообразными для всех проектов, но при этом понимая, что команды, захотят подшаманить некоторые из них. Общий код в проекте был наиболее доступным и удобным для разработчиков майкрософт механизмом.
Dashboard
Запустив AppHost
.NET Aspire вы попадаете на dashboard. Эта панель служит важнейшим инструментом для отладки распределенных приложений, представляя единое представление ваших сервисов вместе с их логами, метриками и trace.
Так же можно чекнуть логи:
Компоненты
Теперь давайте посмотрим, чем отличаются проекты. Во-первых, в веб-проекте есть пакет NuGet с Aspire: Aspire.StackExchange.Redis.OutputCaching
.
Если вы не видите этот пакет у себя, при создании проекта вы не установили флажок "использовать кэширование Redis".
Этот пакет NuGet представляет собой компонент .NET Aspire. Компоненты - это библиотека "клей", которая настраивает SDK для работы в облачной среде. Каждый компонент должен:
- Предоставляет JSON-схему для конфигурации в
appsettings.json
. - Использует настраиваемые шаблоны отказоустойчивости, такие как: retry, тайм-ауты и circuit breaker, чтобы максимизировать доступность.
- Предоставляет helth-check механизм.
- Интегрированные логи, метрики и трассировка с использованием абстракций .NET (
ILogger
,Meter
,Activity
). - Предлагает методы расширения, которые "приклеивают" сервисы из SDK к контейнеру DI с правильным временем жизни для регистрируемых типов.
Код
Теперь давайте посмотрим на код в приложении Blazor, который вызывает API погоды, а затем на код из AppHost
.
В Program.cs вы можете увидеть код следующего вида:
builder.Services.AddHttpClient<WeatherApiClient>(
client => client.BaseAddress = new("http://apiservice"));
Это настройка нашего фронтеда для вызова Weather
API. Но есть несколько необычных моментов, а именно: откуда взялось это имя apiservice
? Чтобы ответить на этот вопрос, мы впервые заглянем в наш проект AppHost
, вот файл Program.cs
из этого проекта:
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedisContainer("cache");
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");
builder.AddProject<Projects.AspireApp_Web>("webfrontend")
.WithReference(cache)
.WithReference(apiservice);
builder.Build().Run();
Этот код выполняется, потому что AppHost
- это ваш startup проект. Он запускает ваши проекты, их зависимости и настраивает их соответствующим образом, позволяя им взаимодействовать. Одна из целей разработчиков Aspire - максимально исключить настройки портов и прописывание connection string'ов с dev flow.
Для этого юзается Service discovery, он так же интегрирован с Polly, что позволяет апплаить политики retry, тайм-аутов и circuit breaker'a.
Подробный обзор Aspire
Компоненты
Компоненты были разработаны, для того, чтобы ускорить разработку и убрать "хаос" в интеграции и конфигурации различных компонентов в приложении, давайте рассмотрим на примере Redis, что нужно было сделать раньше:
- Добавьте Redis package с библиотекой клиента Redis.
- Найдите и добавьте библиотеку helth-check, чтобы ваше приложение могло реагировать на недоступность Redis. Это часто пропускают, но на практике это полезно.
- Добавьте Redis в DI и настройте connection strings. Это непросто, потому что вам нужно знать, какое время жизни должно быть у типов клиентской библиотеки Redis. Что требует ресерча.
- Настройте клиентскую библиотеку Redis на отправку логов в вашу систему телеметрии.
- Журналы и метрики отличаются друг от друга и требуют разного подключения.
- Решите, какая reciliency политика и логика необходима, и настройте Redis или оберните вызовы с помощью библиотеки типа Polly, которая может реализовать политику отказоустойчивости.
Что теперь нужно с .NET Aspire:
- Добавьте пакет .NET Aspire Redis.
- Вызовите
AddRedis
в builder. - Опционально переопределите стандартную конфигурацию в
appSettings.json
.
В обоих приведенных примерах ваш код для использования Redis будет последовательно использовать одну и ту же клиентскую библиотеку Redis и типы.
Чтобы компонент считался готовым к использованию, он должен выполнить следующие действия:
- Предоставьте подробную, схематизированную конфигурацию.
- Настроен Health Checks для отслеживания и реагирования на состояние remote сервисов.
- Предоставляет настраиваемого по умолчанию шаблона отказоустойчивости (повторные попытки, тайм-ауты и т. д.) для обеспечения максимальной доступности.
- Интегрированное логирование, метрики и трассировка, чтобы сделать компонент "observable".
Список доступных компонентов можно найти по ссылке.
На момент написания статьи, доступны следующие:
Cloud-agnostic компоненты:
Component | Description |
---|---|
PostgreSQL Entity Framework Core | Предоставляет клиентскую библиотеку для доступа к базам данных PostgreSQL с помощью Entity Framework Core. |
PostgreSQL | Предоставляет клиентскую библиотеку для доступа к базам данных PostgreSQL. |
RabbitMQ | Предоставляет клиентскую библиотеку для доступа к RabbitMQ. |
Redis Distributed Caching | Предоставляет клиентскую библиотеку для доступа к кэшам Redis для распределенного кэширования. |
Redis Output Caching | Предоставляет клиентскую библиотеку для доступа к кэшам Redis для кэширования вывода. |
Redis | Предоставляет клиентскую библиотеку для доступа к Redis кэшу. |
SQL Server Entity Framework Core | Предоставляет клиентскую библиотеку для доступа к базам данных SQL Server с помощью Entity Framework Core. |
SQL Server | Предоставляет клиентскую библиотеку для доступа к SQL Server. |
Azure компоненты
Component | Description |
---|---|
Azure Blob Storage | Предоставляет клиентскую библиотеку для доступа к Azure Blob Storage. |
Azure Cosmos DB Entity Framework Core | Предоставляет клиентскую библиотеку для доступа к базам данных Azure Cosmos DB с Entity Framework Core. |
Azure Cosmos DB | Предоставляет клиентскую библиотеку для доступа к базам данных Azure Cosmos DB. |
Azure Key Vault | Предоставляет клиентскую библиотеку для доступа к Azure Key Vault. |
Azure Service Bus | Предоставляет клиентскую библиотеку для доступа к Azure Service Bus. |
Azure Storage Queues | Предоставляет клиентскую библиотеку для доступа к Azure Storage Queues. |
Сегодня этот набор компонентов доступен и поставляется компанией Microsoft. Цель состоит в том, чтобы процесс получения компонента Aspire и требования/лучшие практики для них становились все более определяемыми сообществом по мере того, как облако будет меняться и все больше библиотек захотят иметь компоненты для Aspire.
Application Model
AppHost
в приложении .NET Aspire отвечает за оркестровку работы приложения на вашей машине.
Оркестрация .NET Aspire помогает решать следующие задачи:
- Композиция приложения: Определение ресурсов, из которых состоит приложение, включая проекты .NET, контейнеры, исполняемые файлы или облачные ресурсы.
- Service discovery: определение того, как различные ресурсы взаимодействуют друг с другом.
Например, используя .NET Aspire, следующий код создает локальный ресурс контейнера Redis, ресурс проекта для API и настраивает соответствующую строку подключения и URL в проекте "webfrontend".
var builder = DistributedApplication.CreateBuilder(args);
var cache = builder.AddRedisContainer("cache");
var apiservice = builder.AddProject<Projects.AspireApp_ApiService>("apiservice");
builder.AddProject<Projects.AspireApp_Web>("webfrontend")
.WithReference(cache)
.WithReference(apiservice);
builder.Build().Run();
Проект "webfrontend"
теперь может делать HTTP-запросы к http://apiservice
, не заботясь об маппинге портов. Строка подключения к Redis стала еще более прозрачной, поскольку компонент .NET Aspire настраивает клиент Redis на автоматическое использование строки подключения.
Первоначальный набор ресурсов в Aspire приведен ниже:
Built-in ресурсы
- Проект: Проект .NET, например, веб-приложения ASP.NET Core.
- Контейнер: Образ контейнера, например образ Docker.
- Исполняемый файл: Исполняемый файл.
Cloud agnostic компоненты
Каждый из ресурсов становится доступным, когда вы добавляете пакет NuGet для соответствующего ресурса. Для каждого из них вы можете либо запустить контейнер .NET Aspire во время разработки, либо подключиться к существующему/внешнему ресурсу с помощью строк подключения.
- Postgres
- RabbitMQ
- Redis
- SQL Server
Azure Specific
Azure Storage сейчас единственный из этих ресурсов, который поддерживает запуск локального контейнера, для остальных требуется информация о подключении к реальным ресурсам Azure.
- Azure Storage (Blobs, Tables, Queues)
- Azure Cosmos DB
- Azure KeyVault
- Azure Redis Cache
- Azure Service Bus
Developer Dashboard
Подробный обзор можно посмотреть тут.
Observability
Приложения .NET Aspire по умолчанию observable.
Для того чтобы приложение было наблюдаемым:
- Все части distributed приложения должны предоставлять данные таким образом, чтобы вы могли их консюмить, включая сам .NET, библиотеки, которые вы используете, и ваш собственный код приложения.
- Эти данные должны быть отправлены в место, к которому вы можете получить доступ.
- Должны существовать инструменты для просмотра/запроса/понимания этих данных.
Aspire юзает OpenTelemetry по умолчанию, так же, Trace можно посмотреть и на дашборде:
Service Discovery
Одним из ключевых моментов при создании любого распределенного приложения является возможность вызова других сервисов. В рамках .NET Aspire существует библиотека для Service discovery, Microsoft.Extensions.ServiceDiscovery
. Эта библиотека предоставляет основную абстракцию и различные реализации service discovery на стороне клиента и балансировки нагрузки, которые обеспечивают бесшовную интеграцию с HttpClientFactory и YARP, а также в развернутых средах Kuberentes и Azure Container Apps.
Deployment .NET Aspire приложения
Хотя сам .NET Aspire не предоставляет прямого механизма для развертывания приложений, модель приложения, знает все о приложении, его зависимостях, конфигурациях и соединениях с каждым сервисом. Модель приложения может создать манифест, описывающий все эти связи и зависимости, который инструменты могут использовать, дополнять и строить на его основе для развертывания.
Microsoft ожидает, что это будет ключевой компонент, с которым интегрируются многие infrastructure as code системы.
Подробнее про формат можно почитать тут.
Миграция существующих приложений в .NET Aspire
Во-первых, .NET Aspire является частью .NET 8. Поэтому вам нужно будет обновить его, затем нужно заапдейтить VS studio.
После этого вы можете щелкнуть правой кнопкой мыши на проекте в Visual Studio и выбрать Add -> Aspire Orchestrator Support.
Далее подтверждаем выбор:
Это создаст проект AppHost
и ServiceDefaults
, выбранный вами проект уже будет добавлен в AppHost
. Теперь вы можете запустить проект AppHost
и увидите панель разработчика. Отсюда вы можете добавить ссылку на проект ServiceDefaults
и вызвать метод AddServiceDefaults()
в конструкторе приложений. Это позволит настроить Open Telemetry, health check endpoints, service discovery и стандартные шаблоны отказоустойчивости для этого проекта.
Если вы не используете Visual Studio, вы все равно можете добавить проекты AppHost и ServiceDefaults в существующее решение с помощью dotnet new
, но они уже не будут иметь референсі на существующие проекты, как в примере выше.
Следующие шаги
Ну и несколько примеров с юз кейсами:
- Node frontend с .NET Backend: https://github.com/dotnet/aspire-samples/tree/main/samples/AspireWithNode
- DAPR Интеграция: https://github.com/dotnet/aspire-samples/tree/main/samples/AspireWithDapr
- eShop приложуха которая раннится с Aspire: https://github.com/dotnet/eshop
И следите за апдейтами в официальном гитхабе Aspire.
Статья написана по материалам с блога Microsoft.