Сегодня я решил поделиться одной из проблем, с которыми я столкнулся, и решением, которое я нашел для ее решения.

В чем проблема?

В проекте я был разработчиком Nodejs в команде. В бэкэнде проекта у нас есть несколько сервисов, которые работают вместе в микросервисной архитектуре. Эти сервисы пишутся на языке программирования Nodejs.

Проблема возникла, когда мы поняли, что некоторые запросы к микросервису могли занять больше времени, чем обычно, и получили ответ с задержкой.

Итак, мы хотим знать, где приложение проводило большую часть своего времени, и мы не имеем представления о том, что происходит в бэкэнде, почему эти запросы получают больше времени и какой сервис или модуль создают эту проблему.

В последние несколько лет паттерн микросервисной архитектуры стал широко распространенным. Этот шаблон решает многие проблемы проектирования монолитной архитектуры, но имеет некоторые недостатки, одним из самых больших из которых является сложность отладки системы в целом.

В микросервисной архитектуре трассировка является чрезвычайно сложной задачей, поскольку запросы будут охватывать несколько служб, каждая из которых выполняет один или несколько процессов на нескольких серверах.

Распределенная трассировка помогает архитектуре микросервисов!

Один из лучших инструментов, который вы можете иметь при работе с микросервисами, - это распределенная трассировка. Распределенная трассировка позволяет узнать, что происходит в вашей системе и какие части задействованы, даже в производстве.

Так что это время, когда Зипкин может помочь вам отследить ваш запрос.

Что такое Зипкин?

Zipkin - это распределенная система трассировки с открытым исходным кодом , основанная на Google Dapper и изначально разработанная Twitter. Это приложение для распределенной трассировки на основе Java, которое помогает собирать данные о времени для каждого запроса, передаваемого между независимыми службами. Он имеет простую консоль управления, где мы можем визуализировать статистику времени, генерируемую последующими службами.

Компонент в инструментированном приложении, который отправляет данные в Zipkin, называется Reporter. Репортеры отправляют данные трассировки через один из нескольких транспортов в коллекторы Zipkin, которые сохраняют данные трассировки в хранилище. Позже API запрашивает хранилище для предоставления данных пользовательскому интерфейсу.

Первое решение

Поэтому я решил инструментировать свое приложение, добавив трассировку к общим частям кода. Поскольку мой проект был очень большим, я создал простой проект, построил пару микросервисов Express и использовал Zipkin-js для их отслеживания. на основании этой статьи.

После того, как я построил это и использовал в нем трекер, все в порядке, но трассировщик в моем проекте не работал должным образом. Zipkin-js или отображаемый пользовательский интерфейс не отображает правильный диапазон, и сгенерировать диапазон в Zipkin-js сложно, потому что у нас нет полного контроля над ним. Более того, я думаю, что документ Зипкина неполный.

Поэтому я очень расстроился и захотел решить эту проблему. После исследования мой технический директор предложил мне использовать библиотеку OpenTelemtry для клиента трассирующих процессов. Это помогло мне в дальнейшем контролировать диапазон генерации. Поэтому мне пришлось настроить OpenTelemtry, чтобы он мог отправлять трассировки в Zipkin. Другими словами, Zipkinn находится на своем месте в серверной части. OpenTelemtry работает на стороне клиента и использует протокол Zipkin, поэтому он может общаться с Zipkin и отправлять ему трассировку.

Итак, моя проблема изменилась следующим образом:

У меня есть пара микросервисов Express (hello-service-1 и hello-service-2), Zipkin остается на внутреннем сервере, а OpenTelemtry находится в клиенте. Я хочу вызвать hello-service-1 из образца клиента. В hello-service-1 вызовите hello-service-2 и установите трассировку для этого запроса. ясно! вы думаете, что у нас есть 2 услуги, например, вход в систему и покупка. Каждый пользователь должен сначала войти в систему, а затем получить разрешение на совершение покупок. Итак, в этом примере у нас есть 2 службы: вход и покупка. служба покупки вызовите службу входа в систему, чтобы проверить доступ пользователя. В этом примере приобретите как hello-service-1 и войдите как hello-service-2.

Итак, мы хотим отследить запрос, когда он начинается с покупки и переходит в логин. Мы хотим узнать, где именно этот запрос потратил больше времени.

Настройка проекта:

Решение, которое я нашел, - использовать модуль express-http-context для изменения контекста запроса, чтобы я мог установить родительский элемент запроса.

tracer.js:

с createSpan и endSpan теперь я могу легко использовать эту функцию везде, где я хочу отслеживать и создавать или завершать диапазон

Мы собираемся использовать got в качестве нашего HTTP-клиента для выполнения запроса. Чтобы начать работать с Zipkin, нам нужно его инструментировать. Я настроил это вручную:

Использование с Express в качестве промежуточного программного обеспечения:

Теперь, если мы включим обе службы и сделаем запрос к localhost:8081, мы увидим такую ​​трассировку в нашем zipkin-ui:

Теперь мы можем понять, что происходит в наших сервисах, просто взглянув на трассировку. Довольно аккуратно, правда? :)

репозиторий github с полным примером можно найти здесь.