Учебный конструктор · асинхронное общение сервисов
Очереди и события — RabbitMQ, Kafka, Pub/Sub
API — это «спросил и жду ответ». А что, если ждать нельзя: задача долгая, получатель упал, событие нужно сразу многим? Тогда сервисы общаются через брокер сообщений — асинхронно. Собери картину из блоков в трёх моделях: очередь задач (работа воркерам), лог событий (Kafka, переигрывание) и Pub/Sub (копия каждому). Кликай блоки — узнаешь, зачем каждый, а выключив — увидишь, что сломается.
Незнакомы слова (брокер, оффсет, ack, fan-out, идемпотентность…)? → словарь простыми словами внизу. Синхронная сторона — это конструктор API (REST/GraphQL/gRPC).
📋 Очередь задач. Продюсер кладёт задачу в брокер и сразу идёт дальше — не ждёт результат. Брокер держит задачу в очереди, пока её не заберёт свободный воркер. Одна задача достаётся одному воркеру; больше воркеров — быстрее разгребается. Воркер подтверждает (ack) выполнение — пока нет ack, задача не потеряется и достанется другому.
- Клиент шлёт запрос и ЖДЁТ ответ прямо сейчас.
- Отправитель и получатель должны быть онлайн одновременно.
- Получатель упал или тормозит → ошибка/таймаут у клиента.
- Просто и понятно, но сервисы жёстко связаны (tight coupling).
- Хорошо для: «дай данные сейчас», короткие операции, нужен немедленный результат.
- Отправитель кладёт сообщение брокеру и идёт дальше — не ждёт.
- Получатель обработает, когда сможет; быть онлайн одновременно не нужно.
- Брокер — буфер: переживает всплески нагрузки и падения получателя.
- Сервисы развязаны (decoupling), но сложнее: порядок, дубли, гарантии.
- Хорошо для: фоновые задачи, события, всплески, рассылка многим, устойчивость.
# отправитель — положил и пошёл дальше
channel.basic_publish(exchange='', routing_key='tasks',
body='{"id": 42}')
# воркер — взял, сделал, подтвердил
def on_message(ch, method, body):
do_work(body) # обработка
ch.basic_ack(method.delivery_tag) # ✅ ack: теперь можно удалить
channel.basic_consume('tasks', on_message)- basic_publish
- — кладёт задачу в брокер; отправитель не ждёт результата
- routing_key='tasks'
- — в какую очередь положить (через exchange)
- basic_ack
- — подтверждение «сделано» — без него брокер вернёт задачу другому
- basic_consume
- — воркер подписан на очередь; их можно запустить много
Сообщение доставляется максимум один раз: без подтверждений и повторов. Сбой → потеря.
Когда: Где потеря допустима, а дубли вредны: метрики, телеметрия, «лайв»-показания.
Гарантированно доставим, но при сбое ack возможен повтор → дубликаты. Самый частый режим.
Когда: Почти везде. Дубли лечатся идемпотентным консьюмером (ключ идемпотентности / дедуп).
Ровно одна обработка: через транзакции и дедупликацию. Сложно и медленнее.
Когда: Где дубль критичен (деньги). Kafka умеет в пределах своей экосистемы; в общем случае дорого.
📖 Словарь: простыми словами
Встретил незнакомое слово выше — найди его здесь. Коротко — суть; разверни — подробное объяснение с аналогией.
Брокер сообщенийпосредник, принимающий и доставляющий сообщения
Сервис между отправителем и получателем (RabbitMQ, Kafka, Redis). Принимает сообщение, хранит и доставляет — развязывает стороны во времени.
Синхронно / асинхроннождать ответ сейчас / положить и идти дальше
Синхронно (API) — отправил и ждёшь ответ. Асинхронно (очередь) — отдал сообщение брокеру и продолжил работу; получатель обработает позже.
Очередьбуфер сообщений в порядке поступления
Хранит сообщения, пока их не заберёт получатель. Сглаживает всплески: приём и обработка идут каждый в своём темпе. Классически — одно сообщение одному потребителю.
Продюсер / консьюмеротправитель / получатель сообщений
Продюсер (producer) кладёт сообщения, консьюмер (consumer/worker) забирает и обрабатывает. Они не знают друг о друге — общаются через брокер.
Ack (подтверждение)сигнал «обработал успешно»
Консьюмер шлёт брокеру ack после обработки. Только тогда сообщение удаляется. Нет ack (упал воркер) → сообщение вернётся и достанется другому — гарантия «не потерять».
DLQ (dead letter queue)очередь для многократно упавших сообщений
Сообщение, которое не удаётся обработать после N попыток (ядовитое), отправляют в отдельную очередь, чтобы оно не крутилось в ретраях и не блокировало поток.
Идемпотентный консьюмерповтор сообщения не ломает результат
Обработчик, устойчивый к дубликатам: повторная обработка того же сообщения даёт тот же эффект. Реализуется ключом идемпотентности или дедупликацией. Нужен при at-least-once.
Топикименованный лог/канал событий
Категория сообщений (Kafka/PubSub). Продюсеры пишут в топик, потребители читают из него. В Kafka топик — это упорядоченный лог только на дозапись.
Партициячасть топика для параллелизма и порядка
Топик делится на партиции: разные партиции читаются параллельно. Порядок гарантирован только ВНУТРИ партиции; ключ сообщения определяет партицию.
Оффсетпозиция читателя в логе
Номер сообщения в партиции. Каждая группа-консьюмер помнит свой оффсет. Чтение не удаляет сообщение — двигается лишь закладка, можно перечитать.
Consumer groupгруппа читателей одного назначения
Группа делит партиции топика между своими членами (параллелизм). Разные группы читают одни и те же события независимо, каждая со своим оффсетом.
Retentionсколько хранить события в логе
Срок (или размер) хранения событий: 7 дней, N ГБ. В этом окне события можно переигрывать; старое обрезается. У очереди-задач сообщение исчезает после ack, у лога — по retention.
Репликациякопии партиций на разных брокерах
Каждая партиция дублируется на нескольких брокерах (лидер + реплики). Отказ брокера → реплика становится лидером, данные не теряются.
Pub/Subиздатель → копия каждому подписчику
Publish/Subscribe: издатель шлёт сообщение в тему, брокер рассылает копию всем подписчикам (fan-out). Стороны развязаны; обычно без хранения истории (fire-and-forget).
Fan-outодно сообщение → копии многим
Размножение: брокер из одного входящего сообщения делает по копии каждому подписчику темы. Так одно событие запускает много реакций сразу.
Событийная архитектура (event-driven)сервисы реагируют на факты-события
Сервисы не зовут друг друга напрямую, а публикуют события («заказ создан») и реагируют на чужие. Развязывает систему: добавить реакцию = подписать новый сервис.
Гарантии доставкиat-most / at-least / exactly-once
Сколько раз сообщение дойдёт: at-most-once (≤1, можно потерять), at-least-once (≥1, возможны дубли — частый выбор), exactly-once (ровно 1, дорого).
Backpressure (обратное давление)защита от захлёбывания при перегрузе
Когда сообщений приходит больше, чем успевают обрабатывать, система сигналит «помедленнее» или копит в очереди. Без него потребитель захлебнётся.
Порядок сообщенийгарантируется не всегда и не везде
Строгий порядок обычно только внутри одной очереди/партиции. Между партициями порядок не гарантирован — поэтому связанные события шлют с одним ключом.
Развязка (decoupling)сервисы не зависят друг от друга напрямую
Брокер между сторонами убирает жёсткую связь: получатель может упасть, обновиться, масштабироваться — отправитель этого не замечает.
Eventual consistencyсогласованность наступает не мгновенно, а вскоре
В асинхронных системах данные у разных сервисов сходятся «в итоге», с задержкой на обработку сообщений — не атомарно, как в одной БД. Плата за развязку и масштаб.
Ядовитое сообщение (poison)сообщение, которое всегда падает при обработке
Из-за битых данных или бага консьюмер на нём стабильно падает. Без DLQ оно бесконечно повторяется и блокирует очередь; с DLQ — откладывается в сторону.
Дальше по теме
Эти инструменты связаны с текущим — так задачи стыкуются на практике.
Все инструменты — в каталоге.