Software Architect · Модуль 12
Синхронность даёт простую ментальную модель. Асинхронность даёт устойчивость и развязку, но требует новых гарантий.
Queue · event · outbox · backpressure · retry
Выбор sync или async — это выбор между немедленным ответом и устойчивой обработкой во времени.
Синхронный вызов подходит для вопроса
Если кассир спрашивает цену товара, ответ нужен сейчас. Если магазин отправляет отчёт в бухгалтерию, это может занять очередь.
Синхронный запрос хорош, когда пользователю нужен результат прямо сейчас: проверить пароль, показать цену, подтвердить доступ. Он проще для UX и отладки, но связывает availability вызывающего и вызываемого сервиса.
Асинхронность подходит для работы, которую можно выполнить позже: email, indexing, analytics, webhook delivery, report generation, enrichment. Она снижает coupling, но требует статусов, повторов, dead-letter queue и observability.
Событие — это факт, а не команда
«Дверь открыта» — факт. «Открой дверь» — команда. Смешать их можно, но система начнёт спорить о намерениях.
Event описывает то, что уже произошло: OrderPlaced, PaymentCaptured, UserRegistered. Command просит что-то сделать: CapturePayment, SendEmail. В архитектуре полезно не смешивать эти формы.
Если событие используется как скрытая команда, consumer становится зависим от внутреннего намерения producer-а. Это ломает слабую связанность.
Асинхронность не должна быть местом, где ошибки исчезают.
Пример: transactional outbox
Секретарь сначала регистрирует письмо в журнале, а потом отправляет. Если почта упала, запись не потеряна.
При создании заказа сервис пишет order и outbox event в одной транзакции. Отдельный worker читает outbox и публикует событие в broker. Если broker временно недоступен, событие остаётся в базе и будет отправлено позже.
Outbox закрывает типичную дыру: данные сохранились, но событие потерялось между commit и publish.
Антипример: очередь как мусорный бак
Корзина для входящих писем не является процессом. Если её никто не разбирает, работа просто спрятана.
Команда отправляет все тяжёлые операции в очередь, но не задаёт retry policy, idempotency, ordering, visibility timeout, DLQ и алерты. В production сообщения зависают, дублируются или обрабатываются часами.
Очередь не делает систему надёжной автоматически. Она переносит сложность из request path в background processing.
- Нужен ли результат пользователю прямо сейчас? - Что произойдёт при дубле сообщения? - Где хранится факт, что событие должно быть опубликовано? - Как система показывает backlog и failed jobs?