Совет 1: Тщательная настройка AOT-компиляции и GraalVM Native Image. Одна из «фишек» Micronaut — возможность компиляции в нативный образ с помощью GraalVM, что дает беспрецедентную скорость запуска и минимальный размер. Но путь к успешному нативному билду тернист.
- Используйте аннотации `@ReflectiveAccess` и `@Introspected` осторожно и только там, где это действительно необходимо (например, для сериализации сложных DTO). Каждая такая аннотация увеличивает размер образа и усложняет компиляцию.
- Создайте и поддерживайте файл `reflect-config.json` (или используйте аннотации для его генерации) для явного указания классов, требующих рефлексии во время выполнения.
- Настройте CI/CD пайплайн так, чтобы сборка нативного образа происходила в отдельном этапе с достаточными ресурсами (CPU, RAM). Используйте контейнер `graalvm-ce` для воспроизводимости.
- Используйте профили (`micronaut.profiles=prod,aws`) и внешние конфигурационные файлы (`application-prod.yml`).
- Выносите все секреты (пароли БД, API-ключи) в переменные окружения или специализированные хранилища (HashiCorp Vault, AWS Secrets Manager). Для этого в `application.yml` используйте плейсхолдеры: `datasources.default.password: ${DB_PASSWORD:`.
- Настройте четкий порядок загрузки конфигураций, чтобы значения из `application-prod.yml` переопределяли дефолтные, а переменные окружения имели наивысший приоритет.
- Активируйте эндпоинты `/health`, `/metrics`, `/info` и `/loggers` (последний — для динамического изменения уровня логирования в рантайме). В продакшене защитите эти эндпоинты с помощью безопасности или вынесите их на отдельный порт, доступный только внутренней сети.
- Настройте экспорт метрик в Prometheus (`micronaut.metrics.export.prometheus.enabled=true`) и добавьте ключевые бизнес-метрики с помощью `@Timed` или `@Counted`.
- Используйте трассировку для распределенных транзакций. Интегрируйтесь с Jaeger или Zipkin через соответствующую зависимость Micronaut Tracing.
- Для HTTP-клиента, сгенерированного через `@Client`, настройте пул соединений: задайте `read-timeout`, `connection-pool.max-connections` и `connection-pool.max-pending-connections` в конфигурации. Это критически важно для избежания таймаутов и исчерпания файловых дескрипторов при высокой нагрузке.
- Для базы данных (например, с Hibernate/JPA или Jdbi) также настройте пул соединений (HikariCP поставляется по умолчанию). Мониторьте метрики `hikaricp.connections.active` и `idle`.
- Используйте структурированное логирование (JSON-формат) для легкого парсинга в системах типа ELK или Loki. Настройте `logback.xml` для продакшена, отправляя логи сразу в `stdout` (лучшая практика для контейнеров), а не в файлы.
- Контролируйте уровень логирования. Установите уровень `INFO` по умолчанию для всего приложения и `WARN` для шумных пакетов (например, Netty или некоторые части Micronaut). Избегайте логирования целых тел запросов/ответов на уровне `INFO` в продакшене.
- Включите сборку мусора (GC) логирование (`-Xlog:gc*`) для анализа пауз и настройки параметров JVM, даже если вы используете нативный образ (там свой менеджер памяти).
- Используйте токен-базированную аутентификацию (JWT) для сервис-сервисного взаимодействия. Внимательно настройте верификацию подписи и срок действия токенов.
- Для OAuth 2.0 / OpenID Connect настройте правильные `redirect-uri` и используйте надежных провайдеров. Не забудьте про CORS-политики для веб-клиентов.
- Регулярно обновляйте зависимости, особенно `micronaut-security`, чтобы получать исправления уязвимостей.
- Помните, что по умолчанию задачи `@Scheduled` выполняются на том же пуле потоков, что и входящие HTTP-запросы. Для длительных задач создайте отдельный пул через `TaskExecutors`.
- Полностью используйте реактивную природу Micronaut. Возвращайте `Publisher` (Mono/Flux из Project Reactor) из контроллеров и клиентов, чтобы не блокировать event loop и обслуживать больше соединений с меньшим количеством потоков.
- Создавайте многоступенчатые Docker-образы. Для JVM-версии используйте `openjdk:17-slim` как базовый. Для нативного образа — `ubuntu:22.04` или `alpine` (проверьте совместимость glibc).
- В манифестах для Kubernetes укажите корректные `livenessProbe` (на `/health`) и `readinessProbe`, а также лимиты памяти и CPU. Для нативных образов лимиты памяти могут быть в разы меньше.
- Настройте горизонтальное автомасштабирование (HPA) на основе кастомных метрик из Micrometer, например, на количество активных соединений или среднее время отклика.
Комментарии (15)