Discussion group @handle_topic_chat
Contact with me @xepozz
Post #11
242
💬 #Пост №3. Трассировка межсервисного общения
Трассировка запросов – это способ отслеживания запросов между сервисами.
Часто такая надобность появляется, когда система состоит из двух и более сервисов, которые взаимодействуют друг с другом.
Давайте представим, что мы имеем следующую конфигурацию нашей инфраструктуры:
- Продуктовое приложение с бекендом и фронтендом (Application)
- Сервис авторизации (Auth)
Помимо сервисов с бизнес логикой инфраструктура также имеет сборщик различных метрик и логов. Например, Sentry, Newrelic или любой другой сервис.
👤 Юзкейс
- Пользователь выполняет авторизацию в приложении.
- Продуктовое приложение в процессе обработки запроса собирает какие-то логи и отправляет их в систему логов (сборщик).
- Продуктовое приложение делает запрос в сервис авторизации.
- Сервис авторизации выполняет свою часть и так же отправляет собранные логи в сборщик.
🕵️♂️ Трассировка
Когда что-то идёт не так, хочется понимать откуда запрос пришел изначально, какие данные по этому запросы были собраны и какие процессы были выполнены в рамках этого юзкейса.
Один из способов разметить эти процессы – добавить некий ID запроса, который будет сгенерирован, если другая система его не передала или использовать переданный.
В случае юзкейса выше можно на бекенде сгенерировать уникальный ID и передать его в запрос сервиса авторизации. Если используется HTTP, то отлично подойдет секция заголовков (Headers). Наиболее популярное имя такого хедера X-Request-Id.
В этом случае логер должен уметь захватывать этот ID из заголовков и отправлять его контекстом в сборщик логов, а http client отправлять этот ID в Headers других запросов.
Схематично это будет выглядеть так:
1. Запрос Frontend → Application
2. Application Boot. Парсинг или создание нового Request ID в какое-то локальное хранилище, которое в дальнейшем будет использоваться в Logger, HttpClient и других классах для обогащения контекста
3. Запрос Application → Auth
4. Такой же Application Boot, как в пункте №2
Теперь, когда пользователь сделает запрос в продуктовое приложение, мы сможем найти по ID все логи текущего приложения, http запросы в другие сервисы, их логи и дальнейшие запросы. Цепочка может не заканчиваться только на одном сервисе.
Например, цепочка может быть такой:
Представьте, как без такого механизма вы бы могли собрать полную картину межсервисного взаимодействия. По User ID, Remote IP или любым другим косвенным метка одного запроса это делать очень больно.
Помимо HTTP запросов можно так же маркировать сообщения в очередях, если они поддерживают подобие Headers.
Если нет, то можно в тело сообщения добавлять Request ID и уже после распаковки сообщения устанавливать глобальный Request ID для всего приложения.
ℹ️Для консольных команд, а также cron задач, тоже стоит сделать такой механизм.
Инициировать создание Request ID может не только продуктовое приложение, а любой из имеющихся сервисов: биллинг по вебхуку от внешних провайдеров, сервис коммуникаций по крону и так далее.
🏁Итоги
Таким образом, чтобы добавить трассировку межсервисной коммуникации, стоит добавить:
- Механизм генерации ID или получения его от внешних систем при начале работы приложения: http headers, queue headers, queue payload
- Обогатить контекст для подсистем, которые хочется мониторить или которые инициируют запросы в другие системы: http client, queue.
——
Практически под каждый фреймворк есть уже готовые библиотеки, но вы запросто сможете написать свою, под личные ограничения инфраструктуры.
Генерацию http заголовка, кстати, можно делегировать Nginx.
Трассировка запросов – это способ отслеживания запросов между сервисами.
Часто такая надобность появляется, когда система состоит из двух и более сервисов, которые взаимодействуют друг с другом.
Давайте представим, что мы имеем следующую конфигурацию нашей инфраструктуры:
- Продуктовое приложение с бекендом и фронтендом (Application)
- Сервис авторизации (Auth)
Помимо сервисов с бизнес логикой инфраструктура также имеет сборщик различных метрик и логов. Например, Sentry, Newrelic или любой другой сервис.
👤 Юзкейс
- Пользователь выполняет авторизацию в приложении.
- Продуктовое приложение в процессе обработки запроса собирает какие-то логи и отправляет их в систему логов (сборщик).
- Продуктовое приложение делает запрос в сервис авторизации.
- Сервис авторизации выполняет свою часть и так же отправляет собранные логи в сборщик.
🕵️♂️ Трассировка
Когда что-то идёт не так, хочется понимать откуда запрос пришел изначально, какие данные по этому запросы были собраны и какие процессы были выполнены в рамках этого юзкейса.
Один из способов разметить эти процессы – добавить некий ID запроса, который будет сгенерирован, если другая система его не передала или использовать переданный.
В случае юзкейса выше можно на бекенде сгенерировать уникальный ID и передать его в запрос сервиса авторизации. Если используется HTTP, то отлично подойдет секция заголовков (Headers). Наиболее популярное имя такого хедера X-Request-Id.
В этом случае логер должен уметь захватывать этот ID из заголовков и отправлять его контекстом в сборщик логов, а http client отправлять этот ID в Headers других запросов.
Схематично это будет выглядеть так:
1. Запрос Frontend → Application
2. Application Boot. Парсинг или создание нового Request ID в какое-то локальное хранилище, которое в дальнейшем будет использоваться в Logger, HttpClient и других классах для обогащения контекста
3. Запрос Application → Auth
4. Такой же Application Boot, как в пункте №2
Теперь, когда пользователь сделает запрос в продуктовое приложение, мы сможем найти по ID все логи текущего приложения, http запросы в другие сервисы, их логи и дальнейшие запросы. Цепочка может не заканчиваться только на одном сервисе.
Например, цепочка может быть такой:
App -> Write logs; Call ID, Auth, Billing
ID -> Write logs
Auth -> Write logs; Call ID
ID -> Write logs
Billing -> Write logs, Call Auth
Auth -> Write logs; Call ID
ID -> Write logs
Представьте, как без такого механизма вы бы могли собрать полную картину межсервисного взаимодействия. По User ID, Remote IP или любым другим косвенным метка одного запроса это делать очень больно.
Помимо HTTP запросов можно так же маркировать сообщения в очередях, если они поддерживают подобие Headers.
Если нет, то можно в тело сообщения добавлять Request ID и уже после распаковки сообщения устанавливать глобальный Request ID для всего приложения.
ℹ️Для консольных команд, а также cron задач, тоже стоит сделать такой механизм.
Инициировать создание Request ID может не только продуктовое приложение, а любой из имеющихся сервисов: биллинг по вебхуку от внешних провайдеров, сервис коммуникаций по крону и так далее.
🏁Итоги
Таким образом, чтобы добавить трассировку межсервисной коммуникации, стоит добавить:
- Механизм генерации ID или получения его от внешних систем при начале работы приложения: http headers, queue headers, queue payload
- Обогатить контекст для подсистем, которые хочется мониторить или которые инициируют запросы в другие системы: http client, queue.
——
Практически под каждый фреймворк есть уже готовые библиотеки, но вы запросто сможете написать свою, под личные ограничения инфраструктуры.
Генерацию http заголовка, кстати, можно делегировать Nginx.
- 👍 4
- 🌭 1