← Назад к вопросам

В какой ситуации сообщение брокера может не доставиться

2.8 Senior🔥 111 комментариев
#Архитектура и паттерны#Брокеры сообщений

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Причины потери сообщений в брокере

Неуспешная доставка сообщения брокера зависит от архитектуры системы, конфигурации и обработки ошибок. Вот основные ситуации:

1. Потеря сообщений на стороне производителя

Асинхронная отправка без подтверждения:

# Без гарантий доставки
producer.send_async("topic", "message")
# Сообщение может быть потеряно если приложение крахнется

Правильно — ждём подтверждения:

# Гарантия «по крайней мере один раз»
future = producer.send("topic", "message")
record_metadata = future.get(timeout=10)  # Блокирующий вызов
print(f"Доставлено в partition {record_metadata.partition}")

2. Потеря на стороне брокера

Недостаточная репликация:

  • Сообщение записано только на один узел
  • Узел падает до репликации на остальные
  • Решение: настрой min.insync.replicas >= 2, acks=all в Kafka

Неправильная конфигурация:

# Неправильно
producer = KafkaProducer(
    acks=1,
    retries=0
)

# Правильно
producer = KafkaProducer(
    acks='all',
    retries=3,
    max_in_flight_requests_per_connection=1
)

3. Потеря на стороне потребителя

Автоматический коммит смещения до обработки:

# Опасно — offset коммитится до обработки
consumer = KafkaConsumer(
    'topic',
    enable_auto_commit=True,
    auto_commit_interval_ms=1000
)

for message in consumer:
    try:
        process_message(message)
    except Exception:
        pass  # Сообщение потеряно!

Безопасно — ручной коммит после обработки:

consumer = KafkaConsumer(
    'topic',
    enable_auto_commit=False
)

for message in consumer:
    try:
        process_message(message)
        consumer.commit()
    except Exception as e:
        logger.error(f"Ошибка: {e}")
        # Смещение не коммитится — переобработаем

4. Сетевые проблемы

  • Timeout при доставке
  • Потеря пакетов
  • Разрыв соединения

Решение: exponential backoff + retry:

from tenacity import retry, stop_after_attempt, wait_exponential

@retry(
    stop=stop_after_attempt(5),
    wait=wait_exponential(multiplier=1, min=2, max=10)
)
def send_with_retry(broker, message):
    return broker.send(message)

5. Poison pills (токсичные сообщения)

consumer = KafkaConsumer('topic')

for message in consumer:
    try:
        process_message(message)
        consumer.commit()
    except Exception:
        # Отправи в dead-letter queue вместо потери
        dead_letter_queue.send(message)
        consumer.commit()

Итоги

Ключевые гарантии:

  • At most once: быстро, но теряет сообщения
  • At least once: медленнее, но может дублировать
  • Exactly once: гарантия уникальности

Для надёжной системы используй acks=all, ручной коммит, DLQ и мониторинг.

В какой ситуации сообщение брокера может не доставиться | PrepBro