Очереди сообщений: RabbitMQ, Kafka
Очереди сообщений: RabbitMQ, Kafka
1) Когда что выбирать
RabbitMQ (AMQP 0-9-1 / 1.0, классические очереди, Quorum Queues, Streams)
Подходит для: RPC/команд, workflow, коротких задач, fanout/topic маршрутизации, гибких подтверждений, управления приоритетами.
Плюсы: богатая семантика маршрутизации (exchanges), `basic.qos` (prefetch), per-message TTL/delay, удобные паттерны RPC (reply-to), легкий старт.
Минусы: история хранится в очереди, горизонтальное масштабирование по очередям/шардам; высокая Throughput-стоимость при очень больших потоках.
Apache Kafka (лог событий, партиции, consumer groups)
Подходит для: потоков событий, аудита, event sourcing, ETL/интеграций (Connect), высоких RPS/MBps, реплей/ре-процессинг, стрим-процессинга (Streams/ksqlDB).
Плюсы: долговременный журнал, масштабирование по партициям, устойчивый реплей, компактирование ключей.
Минусы: модель «pull + партиции» — не для мелкого RPC; порядок только в пределах партиции; управление схемами/совместимостью — обязанность команды.
2) Семантики доставки и инварианты
At-most-once: без ретраев; быстро, риск потери.
At-least-once: с ретраями; требует идемпотентности потребителя.
Exactly-once: достижимо в ограниченных условиях (Kafka TX + идемпотентный продьюсер + согласованный sink; RabbitMQ — через таблицу дедупа/идемпотентные ключи).
Порядок: RabbitMQ — порядок в очереди (может нарушаться при ретраях/мульти-консьюмерах); Kafka — порядок в партиции, ключ задает партиционирование.
Инварианты домена: деньги/балансы — через журналы/саги и идемпотентные команды; не полагайтесь на LWW.
3) Паттерны интеграции
Outbox/InBox: атомарная запись события в БД → публикация в очередь (outbox) и идемпотентное потребление с логом обработок (inbox).
DLQ (мертвые письма): после N попыток/ошибок — в DLQ + алерт.
Retry/Delay: RabbitMQ — TTL + dead-letter exchange; Kafka — retry-топики с backoff.
Request/Reply: RabbitMQ — `reply_to` + `correlation_id`; Kafka — редко, только спец-паттернами.
Компенсации: саги над событиями; каждая операция имеет обратную.
4) Проектирование ключей и топологий
RabbitMQ
Exchanges: `direct`, `topic`, `fanout`, `headers`.
Routing key: определяет попадание в очередь(и). Для приоритизации — отдельные очереди.
QoS: `prefetch` (например, 50–300) балансирует скорость/латентность.
Quorum Queues: реплицируемые очереди на Raft; замена mirrored classic.
Streams: поток с оффсетами (Kafka-подобно) для high-throughput/реплея.
Kafka
Topic → partitions: планируйте `#partitions` по целевому throughput и параллелизму (обратно совместимо увеличить проще, чем уменьшить).
Key: все записи одного ключа — в одной партиции (гарантия порядка по ключу).
Replication factor: 3 для продуктивных тем, `min.insync.replicas=2` + `acks=all` для надежности.
Retention: по времени/размеру; compaction — хранит последние значения по ключу + tombstones для удаления.
5) Ретраи, DLQ, идемпотентность
RabbitMQ
Повторы: per-message TTL + DLX (dead-letter exchange) с backoff (например, 1м → 5м → 15м).
Идемпотентность: `correlation_id`/`message-id` + таблица обработанных сообщений (TTL) или детерминированные команды.
Подтверждения: manual `basic.ack` после успешной транзакции; `basic.nack(requeue=false)` в DLQ.
Kafka
Повторы: отдельные retry-топики; consumer коммитит оффсет после успешного side-effect.
Exactly-once processing (EOS): Producer `enable.idempotence=true`, транзакционные producer/consumer, `read_committed` на потребителе; sink (например, Kafka→Kafka или Kafka→DB через транзакцию) — аккуратно синхронизировать.
Дедуп: по ключу/идемпотентному ключу на стороне базы, либо через compacted topic.
6) Производительность и размерение
Закон Литтла: `L = λ × W`
Для воркеров: требуемый параллелизм `N ≈ arrival_rate × avg_processing_time × запас(1.2–1.5)`.
RabbitMQ prefetch: начните с `prefetch=100` и измерьте p99/время «ин-флайт».
Kafka partitions: расчет из желаемого consumer-параллелизма и цели по throughput (например, 1 партиция стабильно 5–20 MB/s на SSD/10GbE).
7) Наблюдаемость и алерты
Общее:- Lag/Backlog (сообщений/байт), age сообщений (p95/p99), error-rate обработок, DLQ-rate.
- Время «публикация→обработка» (end-to-end).
- Карта зависимостей: продьюсер → брокер → консюмер.
- Соединения, каналы, не-acked сообщения, `memory_alarm`, `disk_free_limit`, `queue length` p95.
- Отчеты по Quorum (leader, Raft log, промахи `quorum not enough`).
- Under-replicated partitions, ISR shrink/expand, controller changes.
- Producer errors (timeouts, `request latency`), consumer lag per group/partition.
- Broker I/O, page cache hit, GC, ZooKeeper/KRaft health.
8) Безопасность и мульти-тенантность
Шифрование TLS in-transit, аутентификация (SASL/PLAIN/SCRAM/OAuth, mTLS).
Авторизация: vhost/permissions (RabbitMQ), ACL на топики/группы (Kafka).
Квоты: на соединения, каналы, размер очереди/топика, скорость публикации/чтения.
Изоляция по средам (dev/stage/prod) и по namespace/vhost.
9) Эксплуатация и тюнинг
RabbitMQ
Разносите exchanges/queues по узлам (капацитет CPU/IO).
Lazy queues (сообщения на диск) для больших буферов; избегайте «горячих» очередей без шардинга.
Quorum Queues для HA; планируйте размер Raft-журнала и диск.
Политики TTL/length-limit, priority очереди только при реальной нужде (дорого).
bash rabbitmqctl set_policy DLX "^task\." \
'{"dead-letter-exchange":"dlx","message-ttl":60000,"max-length":100000}' --apply-to queues
Kafka
SSD/NVMe, быстрые сети; OS-тюнинг (swappiness низкий, файловые лимиты).
`acks=all`, `linger.ms` (батчирование), `compression.type=zstd`/lz4 для пропускной.
Параметры потребителя: `max.poll.interval.ms`, `max.poll.records`, `fetch.min.bytes`.
Retention и compaction — баланс хранилища/реплея.
java props. put("acks","all");
props. put("enable. idempotence", "true");
props. put("max. in. flight. requests. per. connection","1");
props. put("retries","10");
10) Интеграции и экосистема
Kafka Connect (Sinks/Sources), Schema Registry (Avro/JSON/Protobuf) и совместимость (`BACKWARD/FORWARD/FULL`).
Kafka Streams/ksqlDB: stateful-операции, окна, агрегаты.
RabbitMQ Shovel/Federation: перенос между кластерами/центрами.
Операторы K8s: Strimzi (Kafka), RabbitMQ Cluster Operator; GitOps-манифесты.
11) Чек-лист внедрения (0–45 дней)
0–10 дней
Определить use-case’ы: команды/таски (RabbitMQ), события/аудит (Kafka).
Выбрать ключи (`routing key`/`partition key`), задать SLO «публикация→обработка».
Базовые политики безопасности (TLS, ACL), квоты, DLQ/TTL.
11–25 дней
Внедрить outbox/inbox, идемпотентность и дедуп.
Настроить ретраи с backoff (Rabbit: TTL+DLX; Kafka: retry topics).
Дашборды: lag, age, DLQ-rate, end-to-end latency; алерты.
26–45 дней
Тюнинг пропускной: prefetch/acks (Rabbit); partitions/acks/batch (Kafka).
DR-процедуры (зеркалирование/репликация), тесты отказа узлов.
Документировать контракты событий (схемы) и политику совместимости.
12) Анти-паттерны
Один «универсальный» инструмент на все задачи.
Отсутствие DLQ/TTL: вечные отравители (poison messages).
Неограниченный `prefetch` → голодание потребителей, рост p99.
Kafka без ключей → потеря порядка/горячие партиции по умолчанию.
«Exactly-once» без реальной потребности/дисциплины — ложное чувство безопасности.
Секреты/логины в коде, без TLS/ACL.
Хардкод схем/версий сообщений без Registry и миграций.
13) Метрики зрелости
Lag/age SLO выполняется ≥ 99% времени; DLQ-rate под контролем.
Идемпотентность покрывает 100% критичных путей; outbox/inbox внедрен.
Retention/compaction задокументированы, реплей не ломает потребителей.
Алерты на ISR/URP (Kafka) и Raft/дисковые лимиты (Rabbit) настроены.
Контракты событий версионируются (Schema Registry), совместимость тестируется в CI.
Регулярные game-days: отказ узла/брокера/АЗ, проверка восстановления.
14) Примеры конфигов (сводка)
RabbitMQ: префетч и подтверждения (pseudocode):python channel. basic_qos(prefetch_count=200)
for msg in consume("tasks"):
try:
handle(msg)
channel. basic_ack(msg. delivery_tag)
except Transient:
channel. basic_nack(msg. delivery_tag, request = False) # will go to DLQ
Kafka Consumer (идеи):
java props. put("enable. auto. commit","false");
props. put("isolation. level","read_committed"); // при EOS
//...
poll -> process(idempotent) -> commitSync()
15) Заключение
RabbitMQ и Kafka решают разные классы задач: команды/таски и богатая маршрутизация против долговременного журнала событий и масштабируемого стриминга. Успех — в правильных семантиках доставки, дисциплине идемпотентности, продуманном ключевании, ретраях/DLQ, наблюдаемости и строгой безопасности. Постройте вокруг очередей инженерную практику — outbox/inbox, схемы и GitOps-политики — и ваша интеграция станет предсказуемой, масштабируемой и устойчивой.