Важно отслеживать показатели и работоспособность приложения: это помогает нам повышать производительность, лучше им управлять и замечать неоптимизированное поведение. Мониторинг каждого сервисного модуля важен для поддержания системы, состоящей из множества микросервисов.
В этой статье я покажу, как можно мониторить веб-приложение Spring Boot с помощью Micrometer, который отображает метрики нашего приложения, Prometheus, который хранит их, и Grafana для визуализации этих данных в виде графиков.
Имплементировать эти инструменты довольно легко, добавив всего несколько конфигураций. В дополнение к стандартным метрикам JVM я покажу, как можно предоставлять кастомные, например, счетчик пользователей.
Spring Boot
Основой для нашего демо является приложение Spring Boot, которое мы инициализируем с помощью Spring Initializr:
Мы инициализировали проект с помощью spring-boot-starter-actuator
, который уже предоставляет production-ready endpoints (конечные точки, готовые к продакшену).
Если мы запустим наше приложение, то увидим, что некоторые конечные точки, такие как health
и info
, уже по умолчанию экспонированы в эндпойнт /actuator
.
При запуске конечной точки /actuator/health
мы получаем метрику, если служба запущена и работает:
▶ http GET "http://localhost:8080/actuator/health"
HTTP/1.1 200
Connection: keep-alive
Content-Type: application/vnd.spring-boot.actuator.v3+json
Date: Wed, 21 Oct 2020 18:11:35 GMT
Keep-Alive: timeout=60
Transfer-Encoding: chunked
{
"status": "UP"
}
Spring Boot Actuator может быть интегрирован в Spring Boot Admin, который предоставляет визуальный интерфейс администратора для вашего приложения. Но такой подход не очень популярен и имеет некоторые ограничения. Поэтому мы используем Prometheus вместо Spring Boot Actuator и Grafana вместо Spring Boot Admin, чтобы получить более популярное и независимое от фреймворка/языка решение.
Для данного подхода необходимы платформонезависимые метрики, и Micrometer является наиболее популярным инструментом в данном случае.
Micrometer
Micrometer предоставляет простой фасад поверх клиентов инструментария наиболее популярных систем мониторинга, позволяя вам выполнять инструментарий кода приложений на базе JVM без привязки к производителю. Вспомните мигратор SLF4J, но для метрик.
Micrometer является проектом с открытым исходным кодом и предоставляет метрический фасад, который отображает метрические данные в независимом от поставщика формате, понятном системе мониторинга.
Micrometer не является частью экосистемы Spring и должен быть добавлен в качестве зависимости. В нашем демонстрационном приложении это уже было сделано в конфигурации Spring Initializr.
Следующим шагом будет отображение метрик Prometheus в application.properties
:
management.endpoints.web.exposure.include=prometheus,health,info,metric
Теперь мы можем запустить эту конечную точку и увидеть метрики Prometheus:
Пользовательские метрики
Мы также можем определить некоторые пользовательские метрики, которые я продемонстрирую в этом разделе. Демо содержит класс Scheduler
, который периодически запускает встроенный метод schedulingTask
.
Чтобы иметь возможность отправлять пользовательские метрики, нам нужно импортировать MeterRegistry
из библиотеки Micrometer и вставить его в наш класс. Более подробную информацию можно найти в официальной документации.
Из MeterRegistry
можно инстанцировать следующие типы счетчиков:
Counter: сообщает только о результатах подсчета указанного свойства приложения.
Gauge: показывает текущее значение измерительного прибора
Timers: измеряет задержки или частоту событий
DistributionSummary: обеспечивает дистрибуцию событий и простую итоговую сводку.
Я реализовал counter
и gaude
в демонстрационных целях:
@Component
public class Scheduler {
private final AtomicInteger testGauge;
private final Counter testCounter;
public Scheduler(MeterRegistry meterRegistry) {
// Counter vs. gauge, summary vs. histogram
// https://prometheus.io/docs/practices/instrumentation/#counter-vs-gauge-summary-vs-histogram
testGauge = meterRegistry.gauge("custom_gauge", new AtomicInteger(0));
testCounter = meterRegistry.counter("custom_counter");
}
@Scheduled(fixedRateString = "1000", initialDelayString = "0")
public void schedulingTask() {
testGauge.set(Scheduler.getRandomNumberInRange(0, 100));
testCounter.increment();
}
private static int getRandomNumberInRange(int min, int max) {
if (min >= max) {
throw new IllegalArgumentException("max must be greater than min");
}
Random r = new Random();
return r.nextInt((max - min) + 1) + min;
}
}
Если мы запустим приложение, то увидим, что наши пользовательские метрики отображаются через конечную точку actuatuor/prometheus
:
▶ http GET "http://localhost:8080/actuator/prometheus" | grep custom
# HELP custom_gauge
# TYPE custom_gauge gauge
custom_gauge 29.0
# HELP custom_counter_total
# TYPE custom_counter_total counter
custom_counter_total 722.0
Поскольку теперь у нас есть метрики в формате, понятном Prometheus, посмотрим, как его настроить.
Prometheus
Prometheus хранит наши метрические данные в виде временных рядов в памяти, периодически извлекая их через HTTP. Данные можно визуализировать с помощью языка шаблонов консоли, встроенного браузера выражений или же интегрировав Grafana (что мы сделаем после настройки Prometheus).
В этом демо мы будем запускать Prometheus локально в контейнере Docker, поэтому нам понадобятся некоторые конфигурации из файла prometheus.yml
, который можно разместить в любом месте на жестком диске:
global:
scrape_interval: 10s # How frequently to scrape targets by default
scrape_configs:
- job_name: 'spring_micrometer' # The job name is assigned to scraped metrics by default.
metrics_path: '/actuator/prometheus' # The HTTP resource path on which to fetch metrics from targets.
scrape_interval: 5s # How frequently to scrape targets from this job.
static_configs: # A static_config allows specifying a list of targets and a common label set for them
- targets: ['192.168.178.22:8080']
Все доступные варианты конфигурации описаны в официальной документации.
Поскольку мы хотим запустить Prometheus в контейнере Docker, необходимо указать Prometheus наш IP-адрес взамен localhost
в static_configs -> targets
. Вместо localhost:8080
выбираем 192.168.178.22:8080
, где 192.168.178.22
- это мой IP-адрес в данный момент. Чтобы узнать IP-адрес вашей системы, используйте ifconfig
или ipconfig
в терминале в зависимости от вашей операционной системы.
Теперь мы готовы к запуску Prometheus:
docker run -d -p 9090:9090 -v <path-to-your-prometheus.yml>:/etc/prometheus/prometheus.yml prom/prometheus
<path-to-your-prometheus.yml>
это должен быть путь, куда вы поместили конфигурационный файл prometheus.yml
, описанный выше.
Наконец, мы можем открыть Prometheus на сайте http://localhost:9090
в веб-браузере и найти нашу пользовательскую метрику с именем custom_gauge
:
Чтобы проверить, что Prometheus правильно прослушивает наше локально запущенное приложение Spring Boot, мы можем перейти в Status -> Targets
на главной верхней навигационной панели:
Prometheus предоставляет язык запросов PromQL, более подробную информацию можно найти в официальной документации.
Grafana
Входящий в комплект поставки Prometheus браузер графиков хорош для базовой визуализации наших метрик, но вместо него мы применим Grafana. Grafana предоставляет богатый пользовательский интерфейс, позволяющий создавать, исследовать и совместно использовать дашборды, содержащие несколько графиков.
Grafana может получать данные из различных источников данных, таких как Prometheus, Elasticsearch, InfluxDB и др. Она также позволяет настраивать на основе правил оповещения, которые затем могут уведомлять вас через Slack, Email, Hipchat и т.п.
Мы запускаем Grafana также локально в контейнере Docker:
docker run -d -p 3000:3000 grafana/grafana
При открытии http://localhost:3000
в браузере должна появиться следующая страница авторизации:
Вы можете войти в систему, используя стандартное имя пользователя admin
и пароль admin
. После входа следует изменить эти пароли по умолчанию, посетив страницу http://localhost:3000/profile/password
.
Первым шагом будет добавление нашего локального Prometheus в качестве источника данных:
Дашборд сообщества
Первая приборная панель, которую мы хотим добавить, - это дашборд сообщества. Поскольку в качестве приложения используется Spring Boot, выбираем популярную панель JVM:
После загрузки URL мы видим импортированный дашборд:
Пользовательский дашборд метрик
Наконец, мы хотим создать новый дашборд, где будут отображаться наши пользовательские метрики. Первым шагом будет создание новой приборной панели:
Теперь мы видим новый дашборд, где мы можем создать новую панель:
На первой панели мы добавляем отображение для нашей метрики custom_gauge. Я использую визуализацию Stat, так как она показывает текущее значение и простой график:
Кроме того, в дашборд добавляется новая панель для метрики custom_counter:
В итоге дашборд выглядит следующим образом:
Заключение
Важно контролировать метрики и работоспособность приложения: это помогает нам повысить производительность, лучше управлять приложением и замечать неоптимизированное поведение. Мониторинг каждой службы важен для поддержания системы, состоящей из множества микросервисов.
В этой статье я показал, как можно мониторить веб-приложение Spring Boot с помощью Micrometer, отображающего метрики нашего приложения; Prometheus, хранящего данные метрик; Graphana для визуализации данных в виде графиков.
Этот популярный подход к мониторингу должен способствовать поддержке ваших приложений и радовать клиентов.
Как всегда, код демонстрации, использованной в этой статье, можно найти на GitHub.
Перевод материала подготовлен для будущих студентов курса "Observability: мониторинг, логирование, трейсинг". Всех желающих приглашаем на открытый урок "Grafana: формирование дашбордов". На занятии мы:
— проанализируем возможности по формированию дашбордов;
— разберем, как использовать дашборды и тиражирование, а также переменные;
— посмотрим формирование дашбордов для различных окружений.
Регистрация по ссылке.