Runtime и observability с Aspire
После того как Lino генерирует сервисы, web apps и инфраструктурные ресурсы, Aspire помогает запускать все локально с видимостью. Observability — не роскошь: она показывает, здоровы ли APIs, базы данных, cache, messaging и workers.
В приложениях с events, Outbox, workers, Redis, RabbitMQ и несколькими модулями многие проблемы появляются не только на экране. Они появляются в logs, queues, jobs, migrations, параметрах и runtime-ресурсах. Этот раздел показывает, как смотреть на решение как на работающую систему, а не только как на сгенерированные файлы.
Запуск с Aspire
AppHost централизует локальный запуск решения. Он запускает сервисы, web apps и зависимости, такие как PostgreSQL, Redis, RabbitMQ и workers.
dotnet run --project src/Aspire/AppHost/<ProjectName>.AppHost.csproj
Используйте dashboard, чтобы проверять logs, переменные, endpoints и состояние ресурсов. Если сервис не запускается, начните с AppHost и зависимостей, которые он внедряет.
Aspire делает локальную топологию видимой: APIs, web apps, базы данных, cache, message broker и workers отображаются как связанные ресурсы. Такой обзор помогает находить ошибки конфигурации, которые были бы скрыты при ручном запуске, например неверную connection string, отсутствующий параметр, сервис без endpoint или зависимость, которая еще не поднялась.
- Logs: отслеживайте ошибки инициализации, сбои аутентификации, проблемы migrations и сообщения workers.
- Endpoints: подтверждайте порты, URLs, health checks и ссылки на web apps и APIs.
- Параметры: проверяйте secrets и переменные, переданные в каждый сервис.
- Зависимости: убедитесь, что Redis, RabbitMQ и база данных provisioned, прежде чем диагностировать приложение.
Ресурсы базы данных
Сервисы, сгенерированные Lino, обычно имеют собственные DbContexts, migrations и connection strings. В модульных системах проверяйте, что каждый модуль использует ожидаемую базу данных/schema и что migrations применены в правильном месте.
- Подтверждайте connection strings для каждой среды.
- Запускайте migrations перед тестированием потоков, зависящих от нового schema.
- Отслеживайте сбои подключения и время query.
- Избегайте использования production-базы данных при локальном запуске.
В простом сервисе база данных следует за сервисом. В модульном сервисе база данных принадлежит сервису, но каждый модуль может иметь собственный schema, DbContext, migrations и scripts. Это разделение должно быть видно и в эксплуатации: применяя migrations, перед выполнением подтвердите сервис, модуль, provider и среду.
Сбои базы данных часто проявляются как ошибка API, но причина может быть в AppHost, connection string, ожидающей migration, отсутствующем schema или локальных учетных данных. Поэтому диагностику нужно начинать со всей цепочки: параметр в Aspire, активный ресурс базы данных, примененная migration, правильный DbContext и endpoint, вызывающий ожидаемый модуль.
Redis и cache
Redis можно использовать для cache, временного состояния, tokens, rate limiting или других ресурсов в зависимости от включенных templates. Cache повышает производительность, но вводит invalidation и eventual consistency.
Документируйте ключи, время истечения и источник данных. Никогда не храните чувствительные secrets в cache, не понимая шифрование, срок действия и доступ.
Когда проект использует распределенный cache, несколько экземпляров могут совместно использовать значения, что полезно для горизонтального масштабирования. Когда используется только локальный in-memory cache, каждый процесс хранит собственную копию. Эта разница влияет на поведение в production, нагрузочные тесты и invalidation данных.
| Вопрос | Почему это важно |
|---|---|
| Каков источник данных в cache? | Определяет, как пересчитать значение, когда оно истекает или invalidated. |
| Какой TTL допустим? | Определяет, как долго система терпит потенциально устаревшие данные. |
| Cache задан по tenant, пользователю или глобально? | Предотвращает утечки данных между контекстами и плохо смоделированные ключи. |
RabbitMQ и messaging
Messaging поддерживает integration events и асинхронную коммуникацию. С Outbox приложение не зависит от публикации сообщения в тот же момент, что и транзакция; worker может повторить попытку.
- Проверяйте сгенерированные exchanges, queues и bindings.
- Отслеживайте застрявшие сообщения и неактивных consumers.
- Проектируйте idempotent handlers.
- Используйте корреляционные logs, чтобы проследить путь сообщения.
Integration events полезны именно потому, что producer не должен ждать всех consumers. Но это переносит часть сложности в эксплуатацию: сообщения могут задерживаться, consumers могут падать, payloads могут меняться, а handlers могут выполняться более одного раза. Документация потока должна ясно показывать, какое event публикуется, кто его consume и какое локальное состояние обновляется.
Shadow Entities зависят от этой observability. Если entity tenant или пользователя реплицируется в другие модули через event, сбой consumer может оставить локальную копию устаревшей. Система должна позволять диагностировать event, сообщение, handler и обновление, выполненное в базе данных модуля-consumer.
Hangfire Dashboard
Когда background jobs включены, Hangfire Dashboard помогает проверять recurring jobs, сбои, retries и выполнение обработки Outbox.
Защищайте dashboard в общих средах. Он раскрывает важную операционную информацию и не должен быть публичным без аутентификации и авторизации.
Используйте dashboard как инструмент диагностики, а не как замену logs и метрикам. Он показывает queues, попытки и историю выполнения, но для полного расследования все еще нужны correlation id, структурированные logs и бизнес-контекст, чтобы понять, почему job завершился с ошибкой.
- Retries: проверьте, является ли сбой временным или job будет продолжать падать бесконечно.
- Recurring jobs: подтвердите интервал, batch и среднюю длительность выполнения.
- Outbox: наблюдайте за застрявшими сообщениями, повторной обработкой и handlers с исключениями.
- Безопасность: ограничивайте доступ, потому что payloads и ошибки могут раскрывать чувствительные данные.
Workers и фоновая обработка
Workers выполняют задачи, которые не должны блокировать HTTP-запросы: отправку сообщений, обработку Outbox, очистку, синхронизацию и внешние интеграции.
- Используйте batches, подходящие под объем.
- Определите retries и обработку сбоев.
- Логируйте ошибки с достаточным контекстом для повторной обработки.
- Не скрывайте постоянные сбои в общих logs.
Добавляя worker, также определите частоту, размер batch, поведение при сбое и влияние на домен. Worker, который читает 100 записей каждые несколько секунд, имеет другое операционное поведение, чем ежедневный job; оба нужно наблюдать и масштабировать согласно реальному объему.
Не выполняйте в background то, что должно немедленно отвечать пользователю. Используйте worker для последующих задач, интеграций, уведомлений, повторной обработки и обслуживания. Если use case зависит от результата для завершения транзакции, обрабатывайте его как синхронный flow или моделируйте промежуточное состояние, видимое пользователю.
