Что такое Spring Boot Actuator и какие endpoint'ы он открывает по умолчанию?
Spring Boot Actuator добавляет HTTP-эндпоинты для мониторинга: /actuator/health и /actuator/info открыты по умолчанию, остальные (metrics, env, loggers, threaddump, heapdump) нужно явно разрешить через management.endpoints.web.exposure.include.
Что такое Spring Boot Actuator
Spring Boot Actuator — модуль, который встраивает в приложение набор HTTP-эндпоинтов для мониторинга, диагностики и управления без написания дополнительного кода. Actuator работает поверх стандартного Spring MVC или WebFlux и маршрутизирует эндпоинты через отдельный порт или префикс /actuator.
Зависимость добавляется одной строкой:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Эндпоинты по умолчанию
После подключения зависимости Actuator регистрирует около 20 эндпоинтов, но наружу (web exposure) по умолчанию открыты только два:
- /actuator/health — агрегированный статус приложения: UP / DOWN / OUT_OF_SERVICE. Включает sub-indicators (DB, Redis, Disk).
- /actuator/info — произвольные метаданные из
management.info.*илиMETA-INF/build-info.properties.
Остальные эндпоинты включены (enabled=true), но не экспонированы через HTTP. Это разграничение между enabled и exposed — ключевая деталь, которую проверяют на собеседованиях.
Расширение exposure
Конфигурация через application.yml:
management:
endpoints:
web:
exposure:
include: health,info,metrics,loggers,env,threaddump,heapdump
# или include: "*" — открыть все (только за фаерволом!)
endpoint:
health:
show-details: always # показывать sub-indicators без авторизации
server:
port: 8081 # вынести Actuator на отдельный порт
Реальный пример: кастомный HealthIndicator
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;
@Component
public class ExternalApiHealthIndicator implements HealthIndicator {
private final ExternalApiClient client;
public ExternalApiHealthIndicator(ExternalApiClient client) {
this.client = client;
}
@Override
public Health health() {
try {
boolean ok = client.ping(); // реальный HTTP-вызов
return ok
? Health.up().withDetail("latency", client.lastLatencyMs()).build()
: Health.down().withDetail("reason", "ping returned false").build();
} catch (Exception ex) {
return Health.down(ex).build();
}
}
}
Результат в /actuator/health:
{
"status": "UP",
"components": {
"externalApi": {
"status": "UP",
"details": { "latency": 42 }
},
"db": { "status": "UP" },
"diskSpace": { "status": "UP" }
}
}
Пример: изменение уровня логирования в runtime
# Получить текущий уровень
curl http://localhost:8080/actuator/loggers/com.example.service
# Установить DEBUG без перезапуска
curl -X POST http://localhost:8080/actuator/loggers/com.example.service \
-H 'Content-Type: application/json' \
-d '{"configuredLevel": "DEBUG"}'
Защита эндпоинтов через Spring Security
@Bean
public SecurityFilterChain actuatorSecurity(HttpSecurity http) throws Exception {
http
.securityMatcher("/actuator/**")
.authorizeHttpRequests(auth -> auth
.requestMatchers("/actuator/health", "/actuator/info").permitAll()
.anyRequest().hasRole("ADMIN")
)
.httpBasic(Customizer.withDefaults());
return http.build();
}
Подводные камни
- include: "*" в продакшене без фаервола — открывает /actuator/env (переменные окружения с паролями), /actuator/heapdump (дамп кучи), /actuator/shutdown (остановка приложения). Это реальный вектор атаки.
- show-details: always без авторизации — /actuator/health начинает возвращать внутренние IP-адреса БД, имена хостов Redis и другие данные, полезные атакующему.
- Путаница enabled vs exposed — эндпоинт может быть enabled=true, но не экспонирован через web.
management.endpoint.shutdown.enabled=trueсам по себе не открывает /actuator/shutdown снаружи без добавления вexposure.include. - Actuator на том же порту, что и приложение — если nginx проксирует 443→8080, а Actuator тоже на 8080, он доступен извне. Выносить на отдельный порт (management.server.port=8081) и не пробрасывать его через nginx — стандартная практика.
- heapdump и threaddump весят сотни мегабайт — запросы к этим эндпоинтам под нагрузкой могут вызвать GC-паузу или OOM. Их следует ограничивать по IP или отключать в продакшене.
- Кастомные HealthIndicator синхронные по умолчанию — если внешний сервис тормозит, health-check блокирует поток. Для реактивных приложений нужно реализовывать
ReactiveHealthIndicator. - Метрики Micrometer не бесплатны — каждый тег (URI, метод, статус) создаёт отдельную временну́ю серию. Высококардинальные теги (user_id, request_id) приводят к memory leak в Prometheus/InfluxDB.
- /actuator/info пуст без конфигурации — новички ожидают автоматических данных, но без
spring-boot-maven-pluginсbuild-infogoal или явныхmanagement.info.*свойств эндпоинт возвращает пустой объект.
Common mistakes
- Путать термин «actuator endpoints» с соседним механизмом Spring Boot.
- Не называть границу lifecycle, transaction, thread или request для «actuator endpoints».
- Игнорировать production-эффекты «actuator endpoints»: latency, SQL shape, memory, security или observability.
What the interviewer is testing
- Попросить объяснить механизм «actuator endpoints» на минимальном примере.
- Проверить, видит ли кандидат failure mode и диагностику для «actuator endpoints».
- Уточнить, какие настройки или API меняют «actuator endpoints» в реальном сервисе.