Перейти к основному контенту
NGPP
Кабинет

Учебный конструктор · асинхронное общение сервисов

Очереди и события — RabbitMQ, Kafka, Pub/Sub

API — это «спросил и жду ответ». А что, если ждать нельзя: задача долгая, получатель упал, событие нужно сразу многим? Тогда сервисы общаются через брокер сообщений — асинхронно. Собери картину из блоков в трёх моделях: очередь задач (работа воркерам), лог событий (Kafka, переигрывание) и Pub/Sub (копия каждому). Кликай блоки — узнаешь, зачем каждый, а выключив — увидишь, что сломается.

Незнакомы слова (брокер, оффсет, ack, fan-out, идемпотентность…)? → словарь простыми словами внизу. Синхронная сторона — это конструктор API (REST/GraphQL/gRPC).

📋 Очередь задач. Продюсер кладёт задачу в брокер и сразу идёт дальше — не ждёт результат. Брокер держит задачу в очереди, пока её не заберёт свободный воркер. Одна задача достаётся одному воркеру; больше воркеров — быстрее разгребается. Воркер подтверждает (ack) выполнение — пока нет ack, задача не потеряется и достанется другому.

🔁Синхронно — запрос-ответ (API)
  • Клиент шлёт запрос и ЖДЁТ ответ прямо сейчас.
  • Отправитель и получатель должны быть онлайн одновременно.
  • Получатель упал или тормозит → ошибка/таймаут у клиента.
  • Просто и понятно, но сервисы жёстко связаны (tight coupling).
  • Хорошо для: «дай данные сейчас», короткие операции, нужен немедленный результат.
📨Асинхронно — сообщения (очереди)
  • Отправитель кладёт сообщение брокеру и идёт дальше — не ждёт.
  • Получатель обработает, когда сможет; быть онлайн одновременно не нужно.
  • Брокер — буфер: переживает всплески нагрузки и падения получателя.
  • Сервисы развязаны (decoupling), но сложнее: порядок, дубли, гарантии.
  • Хорошо для: фоновые задачи, события, всплески, рассылка многим, устойчивость.
Кликни блок — описание справа. Выключи — увидишь, что сломается по зависимостям.
▶ Прогон: как сообщение проходит по компонентам
Отправитель
📤
Продюсер
Брокер
📨
Брокер (RabbitMQ)
🔀
Exchange + routing keyне обязателен
📥
Очередь (буфер)
☠️
DLQ — «мёртвые письма»не обязателен
Получатель
🛠️
Воркер (консьюмер)
✅
Подтверждение (ack)
🔁
Повтор (requeue)не обязателен
RabbitMQ (pika)— как это записывается на практике
# отправитель — положил и пошёл дальше
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
— воркер подписан на очередь; их можно запустить много
Гарантии доставки — сколько раз дойдёт сообщение
At-most-once (≤1)
можно потерять, нельзя дублировать

Сообщение доставляется максимум один раз: без подтверждений и повторов. Сбой → потеря.

Когда: Где потеря допустима, а дубли вредны: метрики, телеметрия, «лайв»-показания.

At-least-once (≥1)
не потеряем, но возможны дубли

Гарантированно доставим, но при сбое ack возможен повтор → дубликаты. Самый частый режим.

Когда: Почти везде. Дубли лечатся идемпотентным консьюмером (ключ идемпотентности / дедуп).

Exactly-once (=1)
ровно один раз — дорого

Ровно одна обработка: через транзакции и дедупликацию. Сложно и медленнее.

Когда: Где дубль критичен (деньги). 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 — откладывается в сторону.

Дальше по теме

Эти инструменты связаны с текущим — так задачи стыкуются на практике.

Все инструменты — в каталоге.