Misha_Backend
2026-08-03 08:51
Заметил тренд: все кинулись пихать Kafka и RabbitMQ куда ни попадя, даже там, где обычный REST-вызов решает задачу проще и надёжнее. В итоге получаем распределённый монолит на событиях, где трассировка запроса превращается в квест с детективом, а дебаг — в археологические раскопки.
Давайте разберёмся на пальцах. Request-driven — это когда сервис A напрямую дёргает сервис B по HTTP/gRPC и ждёт ответ. Просто, предсказуемо, легко тестировать. Минусы — синхронная связность, каскадные фейлы, и если B лёг — A тоже лежит. Event-driven — это когда A шлёт событие в брокер, а B, C и D подписываются и делают что хотят. Асинхронно, слабо связано, но появляется ад с идемпотентностью, порядком сообщений и eventual consistency.
Типичная ошибка новичка: они видят слово «масштабирование» и сразу пишут топик на каждое чихание. Пример из практики: у нас был сервис заказов, который после создания заказа публиковал 5 разных событий — order_created, payment_started, inventory_reserved, notification_sent, audit_logged. В итоге чтобы понять, что заказ вообще создан, нужно было собирать пазл из пяти топиков и трёх consumer-групп. А ведь достаточно было одного REST-вызова к inventory и fire-and-forget событию для аудита.
Правило, которое я вывел для себя за годы: если событие влияет на бизнес-процесс и требует гарантированного выполнения — это request. Если это уведомление, аналитика или побочный эффект — event. Классика: оплата — request (нужен ответ, иначе юзер занервничает), отправка email-уведомления — event (можно потерять, никто не умрёт).
Ещё одна боль — саги. Все любят саги, пока не приходится дебажить компенсацию на третьем шаге, когда payment уже списал, а stock не освободился. Я видел саги на 15 шагов с ручными retry и DLQ, которые в проде превращаются в тикающий бомбовый механизм. Мой совет: сначала сделайте request-driven версию с явными таймаутами и ретраями, потом если реально упрётесь в нагрузку — рефакторите на события.
И последний пункт — observability. В request-driven мире у тебя есть correlation_id и ты видишь весь путь запроса в Jaeger. В event-driven — каждый consumer имеет свой span, и чтобы связать их, нужно тащить trace_id через заголовки событий, что половина команд забывает. Итог — в Grafana ты видишь, что consumer упал, но почему и из-за какого события — хрен поймёшь.
К чему я это всё: не гонитесь за модой. Архитектура должна решать бизнес-задачи, а не тешить ЧСВ архитектора. Если ваш проект — типичный CRUD на 5 сервисов, события вам нужны только для аудита и уведомлений. А если уж зашли на event-driven — закладывайте идемпотентность, саги и трассировку с первого дня, иначе потом перепишете всё с нуля.
👍 2