Solution Architect
· 01.04Мониторим и дебажим сложные бизнес-транзакции
В распределенных системах бизнес-транзакции редко совпадают с классическими ACID-транзакциями, ну это #яснопонятно(👆про это постом выше 👆). Помним про один из ключевых способов, решающих эту задачу, — Saga; обсудив различные ее виды, включая разницу между оркестрацией и хореографией, мы так и не ответили на вопросы что делать, когда «все ложится звездой» и «как отследить выполнение бизнес-транзакции, размазанной по нескольким сервисам»? Сама концепция шаблона подразумевает использование множества атомарных шагов, каждый из которых выполняется(или нет) в отдельном сервисе. Тут все ок, но что делать если: 1️⃣ Шаг завершился с ошибкой, а компенсация не сработала. 2️⃣ Сообщение потерялось, из-за чего процесс завис в промежуточном состоянии. 3️⃣ Компенсация запустилась поздно или не запустилась вовсе.
🤷♂️🤯🤷♂️🤯🤷♂️🤯
Для начала стоит вообще поговорить, как бы нам упростить себе жизнь в «распределе», а затем ответить на вопросы выше?
1️⃣ Outbox Pattern Известная проблема Dual Write Problem решается довольно изящно и просто с помощью Outbox Pattern, т.е: - Вместо прямой отправки события в брокер сообщений, сервис сначала записывает его в отдельную таблицу БД. - Фоновый процесс читает из этой таблицы и отправляет сообщения в брокер. - Гарантирует, что сообщение либо будет обработано, либо останется в БД для повторной попытки.
2️⃣ Retry & Backoff Strategy Некоторые ошибки (например, временная недоступность сервиса) можно исправить повторной попыткой, это так, но простые ретраи могут создать дополнительную нагрузку, поэтому стоит обратить внимание на: - Exponential Backoff — инкриментально увеличивает паузу между попытками достучаться до внешней системы. - Jitter — добавлять случайность в задержку, чтобы избежать лавинообразных нагрузок. - Dead Letter Queue (DLQ) — отправлять сообщения в отдельную очередь, если они не обработаны после нескольких попыток, мол «последний привет из ада»
3️⃣ Idempotency Key
Чтобы избежать повторного выполнения одного и того же шага в Saga из-за сбоев сети или дублирования сообщений, стоит использовать идемпотентные операции:
- Использовать идемпотентные ключи (например, уникальный TransactionID
).
- Проверять, был ли уже обработан этот шаг.
- Перед обработчиком запросов извне применять шаблон Inbox.
- Не выполнять повторные действия, если они уже зафиксированы в БД. (ON CONFLICT DO NOTHING)
4️⃣ Distributed Tracing Jaeger, Zipkin, OpenTelemetry помогают визуализировать поток запросов между сервисами, что добавляет: - Наглядность в последовательности шагов. - Выявление узких места и задержки. - Отслеживание, на каком шаге произошел сбой.
5️⃣ Monitoring & Alerting Тут подход очень простой - мы должны первыми знать, если в системе что-то идет не так, поэтому метрики - ваше все. Что будет полезным собирать? - Количество успешных / неуспешных завершений Saga. - Среднее время выполнения бизнес-транзакции. - Количество запущенных компенсационных транзакций. - Зависшие процессы, которые требуют ручного вмешательства.
Итак: ❗Шаг завершился с ошибкой, а компенсация не сработала: добавляем метрики, реализуем повторную доссылку компенсаций, на принимающей стороне компенсаций внедряем OUTBOX и/или DLQ ❗Сообщение потерялось, из-за чего процесс завис в промежуточном состоянии: добавляем метрики и мониторинг ❗Компенсация запустилась поздно или не запустилась вовсе: мониторим, DLQ в случае наступления дедлайна для реагирования
#dev #arch #softwareengineeringеще контент автора
еще контент автора
Solution Architect
· 01.04войдите, чтобы увидеть
и подписаться на интересных профи