В современном мире все больше IT-проектов переходят на микросервисную архитектуру. При таком подходе появляется ряд вопросов — как избитых, так и не самых очевидных. Как обеспечить корректную работу системы из большого числа микросервисов? Каким способом и с помощью каких технологий разворачивать этот зоопарк? Как отследить узкие места в производительности?
Меня зовут Максим, я Java-разработчик в SimbirSoft. Сейчас работаю на финтех-проекте, занимаюсь созданием бизнес-логики, иногда подключаюсь к различным техническим задачам. В этой статье я кратко и понятно опишу, что такое трассировки, как устроен Jaeger, а также расскажу про недавно появившийся новый стандарт распределенного трейсинга и мониторинга — OpenTelemetry.
Материал будет полезен начинающим разработчикам. Из него вы узнаете, как с небольшими усилиями подключить трассировки к своему проекту. Речь пойдет об инструменте из большого блока «Наблюдаемость» (Monitoring), а конкретно — о трассировках.

Что такое трассировка?
Трассировка — это метод, который используют для профилирования и мониторинга приложений, особенно тех, которые созданы с использованием архитектуры микросервисов. Трассировка помогает точно определить, где возникают сбои и что вызывает низкую производительность.
Трассировки оперируют понятиями span и trace. Span — это некоторое действие, которое содержит в себе следующие части:
-
название сервиса;
-
уникальный ID;
-
ID родительского спана;
-
название вызываемого метода;
-
время начала и окончания.
Трассировка — это набор/список span, которые соединены отношением родитель/потомок (его также можно рассматривать как направленный ациклический граф отрезков). Трассировки указывают, как запросы распространяются через наши службы и другие компоненты.

Чем она полезна?
Трассировка помогает обнаружить узкие места в производительности. Это возможно благодаря следующим функциям:
-
отслеживание обращения к ресурсам (БД, внешняя система, файлы и т.д);
-
отслеживание последовательного вызова нескольких сервисов;
-
сбор массива данных для последующего анализа при помощи метрик;
-
возможность получить наглядное представление о том, в какой последовательности вызываются сервисы.

Архитектура Jaeger
Также стоит упомянуть о Jaeger. Jaeger — это платформа распределенной трассировки с открытым исходным кодом, созданная Uber еще в 2015 году. Она состоит из инструментальных SDK, серверной части для сбора и хранения данных, пользовательского интерфейса для визуализации данных и платформы Spark/Flink для совокупного анализа трассировки.
Основные части платформы:
-
Инструментальный SDK — библиотеки, необходимые для сбора метрик.
-
Jaeger-agent — локальный агент. Если агента нет, то трейсы всех сервисов на этой машине обычно выключены.
-
Jaeger-collector — в него все агенты посылают собранные трейсы, а он кладет их в выбранную БД.
-
Jaeger-query — сервис, который ходит в базу данных и отдает уже собранные трейсы для анализа.
-
Jaeger-ui — веб-интерфейс для поиска и просмотров трейсов. Он ходит в Jaeger-query.
Локальный запуск Jaeger при помощи Docker в приложениях Spring Boot
Для начала создадим два простых сервиса — Consumer и Producer. Первый будет обращаться по http ко второму, получать слово “hello” и выводить слово “hello-world”.
Рассмотрим контроллер первого сервиса — Consumer. Все стандартно — RestController, GetMapping, Lombok и т.д., кроме feignClient. Способы взаимодействия между сервисами — тема не этой статьи, но в нашем случае используется обычный feignClient. В двух словах, spring-cloud-starter-openfeign позволяет с минимальными усилиями обеспечить сетевое взаимодействие между сервисами.
@RestController @RequiredArgsConstructor public class ConsumerController { private final ProducerFeign producerFeign; @GetMapping(value = "/hello-world") public String getHelloWorld() { return producerFeign.getHello() + " world"; } }
Обратимся к клиенту. При обращении к методу getHello() по localhost:8081/hello получаем слово “hello”.
@FeignClient(name = "producer-feign", url = "localhost:8081") public interface ProducerFeign { @GetMapping(value = "/hello") String getHello(); }
Контроллер нашего второго сервиса (клиента, к которому обращается первый) — Producer.
@RestController @RequiredArgsConstructor public class ProducerController { @GetMapping(value="/hello") public String getHello() { return "hello"; } }
Локальный запуск Jaeger при помощи Docker
Jaeger поставляется в качестве готового образа Docker. Для запуска образа Jaeger выполняем следующее:
docker run -d --name jaeger \ -e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \ -p 5775:5775/udp \ -p 6831:6831/udp \ -p 6832:6832/udp \ -p 5778:5778 \ -p 16686:16686 \ -p 14250:14250 \ -p 14268:14268 \ -p 14269:14269 \ -p 9411:9411 \ jaegertracing/all-in-one:1.6
Далее необходимо запустить наше приложение. В этом руководстве будет использован новый стандарт OpenTelemetry. Все, что нужно сделать — это запустить jar-приложение с параметром javaagent.
OpenTelemetry — относительно новый стандарт. Он включает в себя распределенный трейсинг и мониторинг и совместим с OpenTracing и OpenCensus. Более того, последние прекращают поддержку в течение двух лет, что неотвратимо приближает нас к переходу на OpenTelemetry.
Стандарт, по сути, представляет собой некую прослойку между потребителями метрик/трейсов и их поставщиками.

В документации OpenTelemetry можно найти параметры, с которыми запускается jar (например, OTEL_TRACES_EXPORTER, OTEL_SERVICE_NAME и т.д.). Параметр Dotel.traces.exporter определяют куда opentelemetry будет складывать трейсы, в нашем случае это Jaeger.
Запуск первого сервиса:
java -javaagent:{your-path-to-agent}/opentelemetry-javaagent.jar -Dotel.traces.exporter=jaeger -Dotel.service.name=customer-consumer -jar customer-consumer-0.0.1-SNAPSHOT.jar
Запуск второго сервиса:
java -javaagent:{your-path-to-agent}/opentelemetry-javaagent.jar -Dotel.traces.exporter=jaeger -Dotel.service.name=customer-producer -jar customer-producer-0.0.1-SNAPSHOT.jar
Для перехода в пользовательский интерфейс Jaeger используем http://localhost:16686/

Вывод
Трассировка — очень мощный инструмент, который помогает локализовать сбои и с точностью определить, что приводит к низкой производительности. Этот метод позволяет стабилизировать поведение в распределенных системах, собирать данные для последующего анализа при помощи метрик и наглядно показывает цепочку вызовов компонентов системы.
Чтобы получить максимальную отдачу от использования инструмента, ваши сервисы должны отправлять трассировки на центральную панель мониторинга — например, Jaeger. В этой статье мы рассмотрели лишь часть функциональности OpenTelemetry. На самом деле, возможности стандарта намного шире.
Если вам интересна эта тема — сохраните полезные ссылки:
-
Документация по OpenTelemetry с дружелюбным пособием для начинающих: https://opentelemetry.io/
-
Документация по Jaeger: https://www.jaegertracing.io/
Спасибо за внимание!
Больше полезных материалов для backend-разработчиков мы также публикуем в наших соцсетях – ВК и Telegram.
ссылка на оригинал статьи https://habr.com/ru/articles/740152/
Добавить комментарий