1. Обзор
Spring Boot предоставляет несколько различных способов проверки состояния и работоспособности запущенного приложения и его компонентов. Среди этих подходов два наиболее заметных API HealthContributor
и HealthIndicator .
В этом руководстве мы познакомимся с этими API, узнаем, как они работают, и посмотрим, как мы можем добавлять в них пользовательскую информацию.
2. Зависимости
Вкладчики информации о работоспособности являются частью исполнительного модуля Spring Boot , поэтому нам нужна соответствующая зависимость Maven :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
3. Встроенные индикаторы здоровья
По умолчанию
Spring Boot регистрирует множество `` HealthIndicator , чтобы сообщать о работоспособности определенного аспекта приложения .
Некоторые из этих индикаторов почти всегда регистрируются, например DiskSpaceHealthIndicator
или PingHealthIndicator
. Первый сообщает о текущем состоянии диска, а второй служит конечной точкой проверки связи для приложения.
С другой стороны, Spring Boot некоторые индикаторы прописывает условно . То есть, если некоторые зависимости находятся в пути к классам или выполняются некоторые другие условия, Spring Boot также может зарегистрировать несколько других HealthIndicator
s. Например, если мы используем реляционные базы данных, Spring Boot регистрирует DataSourceHealthIndicator
. Точно так же он зарегистрирует CassandraHealthIndicator
, если мы будем использовать Cassandra в качестве хранилища данных.
Чтобы проверить состояние работоспособности приложения Spring Boot, мы можем вызвать конечную точку /actuator/health
. Эта конечная точка сообщит об агрегированном результате всех зарегистрированных HealthIndicator
s.
Кроме того, чтобы просмотреть отчет о работоспособности по одному конкретному индикатору, мы можем вызвать конечную точку /actuator/health/{name}
. Например, вызов конечной точки /actuator/health/diskSpace
вернет отчет о состоянии из DiskSpaceHealthIndicator
:
{
"status": "UP",
"details": {
"total": 499963170816,
"free": 134414831616,
"threshold": 10485760,
"exists": true
}
}
4. Пользовательские индикаторы
здоровья
В дополнение к встроенным, мы можем зарегистрировать пользовательские HealthIndicator
, чтобы сообщать о работоспособности компонента или подсистемы. Для этого все, что нам нужно сделать, это зарегистрировать реализацию интерфейса HealthIndicator
как компонент Spring .
Например, следующая реализация сообщает об ошибке случайным образом:
@Component
public class RandomHealthIndicator implements HealthIndicator {
@Override
public Health health() {
double chance = ThreadLocalRandom.current().nextDouble();
Health.Builder status = Health.up();
if (chance > 0.9) {
status = Health.down();
}
return status.build();
}
}
Согласно отчету о работоспособности этого индикатора, приложение должно работать только 90% времени. Здесь мы используем Health
Builders, чтобы сообщать информацию о здоровье.
Однако в реактивных приложениях мы должны зарегистрировать bean-компонент типа ReactiveHealthIndicator
. Реактивный метод health() возвращает
Mono<Health>
вместо простого Health
. Кроме этого, другие детали одинаковы для обоих типов веб-приложений.
4.1. Название индикатора
Чтобы просмотреть отчет по этому конкретному индикатору, мы можем вызвать конечную точку /actuator/health/random
. Например, вот как может выглядеть ответ API:
{"status": "UP"}
Случайный
в URL - адресе /actuator/health/random
является идентификатором этого индикатора. Идентификатор конкретной реализации HealthIndicator
равен имени компонента без суффикса HealthIndicator
. Поскольку имя компонента — randomHealthIdenticator
, префикс random
будет идентификатором.
С помощью этого алгоритма, если мы изменим имя компонента, скажем, на rand
:
@Component("rand")
public class RandomHealthIndicator implements HealthIndicator {
// omitted
}
Тогда идентификатор индикатора будет rand
вместо random
.
4.2. Отключение индикатора
Чтобы отключить определенный индикатор, мы можем установить для свойства конфигурации management.health.<indicator_identifier >
.enabled
значение false
. Например, если мы добавим следующее в наш application.properties
:
management.health.random.enabled=false
Затем Spring Boot отключит RandomHealthIndicator
. Чтобы активировать это свойство конфигурации, мы также должны добавить аннотацию @ConditionalOnEnabledHealthIndicator
к индикатору:
@Component
@ConditionalOnEnabledHealthIndicator("random")
public class RandomHealthIndicator implements HealthIndicator {
// omitted
}
Теперь, если мы вызовем /actuator/health/random
, Spring Boot вернет HTTP-ответ 404 Not Found:
@SpringBootTest
@AutoConfigureMockMvc
@TestPropertySource(properties = "management.health.random.enabled=false")
class DisabledRandomHealthIndicatorIntegrationTest {
@Autowired
private MockMvc mockMvc;
@Test
void givenADisabledIndicator_whenSendingRequest_thenReturns404() throws Exception {
mockMvc.perform(get("/actuator/health/random"))
.andExpect(status().isNotFound());
}
}
Обратите внимание, что отключение встроенных или пользовательских индикаторов аналогично друг другу. Следовательно, мы можем применить ту же конфигурацию и к встроенным индикаторам.
4.3. дополнительные детали
В дополнение к отчету о статусе мы можем прикрепить дополнительные сведения о ключе-значении, используя withDetail(key, value)
:
public Health health() {
double chance = ThreadLocalRandom.current().nextDouble();
Health.Builder status = Health.up();
if (chance > 0.9) {
status = Health.down();
}
return status
.withDetail("chance", chance)
.withDetail("strategy", "thread-local")
.build();
}
Здесь мы добавляем две части информации в отчет о состоянии. Кроме того, мы можем добиться того же, передав Map<String, Object>
методу withDetails(map)
:
Map<String, Object> details = new HashMap<>();
details.put("chance", chance);
details.put("strategy", "thread-local");
return status.withDetails(details).build();
Теперь, если мы вызовем /actuator/health/random
, мы можем увидеть что-то вроде:
{
"status": "DOWN",
"details": {
"chance": 0.9883560157173152,
"strategy": "thread-local"
}
}
Мы также можем проверить это поведение с помощью автоматизированного теста:
mockMvc.perform(get("/actuator/health/random"))
.andExpect(jsonPath("$.status").exists())
.andExpect(jsonPath("$.details.strategy").value("thread-local"))
.andExpect(jsonPath("$.details.chance").exists());
Иногда возникает исключение при обмене данными с системным компонентом, таким как база данных или диск. Мы можем сообщить о таких исключениях, используя метод withException(ex)
:
if (chance > 0.9) {
status.withException(new RuntimeException("Bad luck"));
}
Мы также можем передать исключение методу down(ex)
, который мы видели ранее:
if (chance > 0.9) {
status = Health.down(new RuntimeException("Bad Luck"));
}
Теперь отчет о работоспособности будет содержать трассировку стека:
{
"status": "DOWN",
"details": {
"error": "java.lang.RuntimeException: Bad Luck",
"chance": 0.9603739107139401,
"strategy": "thread-local"
}
}
4.4. Детали Экспозиция
Свойство конфигурации management.endpoint.health.show-details управляет уровнем детализации, который может предоставлять каждая конечная точка работоспособности.
Например, если мы установим для этого свойства значение « всегда»,
то Spring Boot всегда будет возвращать поле сведений
в отчете о работоспособности, как в приведенном выше примере.
С другой стороны, если мы установим для этого свойства значение never
, то Spring Boot всегда будет опускать детали
из вывода . Существует также значение when_authorized
, которое предоставляет дополнительные сведения
только для авторизованных пользователей. Пользователь авторизован тогда и только тогда, когда:
- Она аутентифицирована
- И она обладает ролями, указанными в свойстве конфигурации
management.endpoint.health.roles .
4.5. Состояние здоровья
По умолчанию Spring Boot определяет четыре разных значения в качестве состояния работоспособности
:
UP —
компонент или подсистема работает должным образомВНИЗ
— Компонент не работаетOUT_OF_SERVICE
— компонент временно не работаетUNKNOWN
— Состояние компонента неизвестно
Эти состояния объявляются как общедоступные статические конечные
экземпляры вместо перечислений Java. Таким образом, можно определить наши собственные состояния работоспособности. Для этого мы можем использовать метод status(name)
:
Health.Builder warning = Health.status("WARNING");
Состояние работоспособности влияет на код состояния HTTP конечной точки работоспособности . По умолчанию Spring Boot отображает состояния DOWN
и OUT_OF_SERVICE
, чтобы выдать код состояния 503. С другой стороны, UP
и любые другие несопоставленные статусы будут преобразованы в код состояния 200 OK.
Чтобы настроить это сопоставление, мы можем установить для свойства конфигурации management.endpoint.health.status.http-mapping.<status> желаемый номер кода состояния HTTP:
management.endpoint.health.status.http-mapping.down=500
management.endpoint.health.status.http-mapping.out_of_service=503
management.endpoint.health.status.http-mapping.warning=500
Теперь Spring Boot сопоставит статус DOWN
с 500, OUT_OF_SERVICE
с 503 и WARNING
с 500 кодами состояния HTTP:
mockMvc.perform(get("/actuator/health/warning"))
.andExpect(jsonPath("$.status").value("WARNING"))
.andExpect(status().isInternalServerError());
Точно так же мы можем зарегистрировать bean-компонент типа HttpCodeStatusMapper
, чтобы настроить сопоставление кода состояния HTTP :
@Component
public class CustomStatusCodeMapper implements HttpCodeStatusMapper {
@Override
public int getStatusCode(Status status) {
if (status == Status.DOWN) {
return 500;
}
if (status == Status.OUT_OF_SERVICE) {
return 503;
}
if (status == Status.UNKNOWN) {
return 500;
}
return 200;
}
}
Метод getStatusCode(status)
принимает состояние работоспособности в качестве входных данных и возвращает код состояния HTTP в качестве выходных данных. Кроме того, можно сопоставить пользовательские экземпляры состояния :
if (status.getCode().equals("WARNING")) {
return 500;
}
По умолчанию Spring Boot регистрирует простую реализацию этого интерфейса с сопоставлениями по умолчанию. SimpleHttpCodeStatusMapper также может считывать
сопоставления из файлов конфигурации, как мы видели ранее.
5. Медицинская информация и показатели
Нетривиальные приложения обычно содержат несколько разных компонентов. Например, рассмотрим приложения Spring Boot, использующие Cassandra в качестве своей базы данных, Apache Kafka в качестве платформы публикации и подписки и Hazelcast в качестве сетки данных в памяти.
Мы должны использовать HealthIndicator
, чтобы увидеть, может ли приложение взаимодействовать с этими компонентами или нет . Если канал связи выходит из строя или сам компонент не работает или работает медленно, то у нас есть неработоспособный компонент, о котором мы должны знать. Другими словами, эти индикаторы следует использовать для сообщения о работоспособности различных компонентов или подсистем.
Напротив, нам следует избегать использования HealthIndicator
для измерения значений, подсчета событий или измерения длительности. Вот почему у нас есть метрики. Проще говоря, метрики — это лучший инструмент для создания отчетов об использовании ЦП, средней нагрузке, размере кучи, распределении ответов HTTP и т. д.
6. Заключение
В этом руководстве мы увидели, как добавить больше информации о работоспособности в конечные точки работоспособности привода. Кроме того, мы подробно рассмотрели различные компоненты в API-интерфейсах работоспособности, такие как Health
, Status
и статус отображения состояния HTTP.
В завершение мы быстро обсудили разницу между информацией о здоровье и показателями, а также узнали, когда использовать каждый из них.
Как обычно, все примеры доступны на GitHub .