Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

Документы

Медиа

Назад
Вопрос про Node.js: Apache Kafka, event-driven architecture, message broker, producer, consumer, idempotency

Как спроектировать систему отправки событий (например, чеков) с использованием Kafka?

Вопрос проверяет умение проектировать отказоустойчивые асинхронные системы обработки событий с использованием Apache Kafka, что необходимо для построения масштабируемых микросервисных архитектур.

Короткий ответ

Система отправки событий на Kafka строится вокруг продюсеров, которые публикуют сообщения (например, чеки) в топики. Kafka гарантирует надежное хранение сообщений с репликацией. Консьюмеры, организованные в группы, читают эти сообщения для дальнейшей обработки (сохранение в БД, отправка уведомлений). Ключевые аспекты проектирования: идемпотентность продюсера для избежания дублей, правильный выбор ключа партиционирования для порядка событий и обработка ошибок в консьюмерах.

Длинный ответ

Проектирование системы отправки событий, такой как чеки, с использованием Apache Kafka, требует понимания её роли как распределённого лога сообщений. Основная цель — обеспечить надёжную, масштабируемую и отказоустойчивую передачу данных между различными частями системы (микросервисами).

Ключевые компоненты архитектуры

Архитектура строится на нескольких основных концепциях Kafka:

  • Producer (Продюсер): Сервис, генерирующий события (например, сервис заказов после успешной оплаты). Он отправляет сообщения (чеки) в определённый топик Kafka.
  • Topic (Топик): Именованный поток данных, например, purchase-receipts. Топики делятся на партиции для горизонтального масштабирования.
  • Consumer (Консьюмер): Сервис, который подписывается на топик и обрабатывает сообщения. Например, сервис нотификаций для отправки email или сервис аналитики для сохранения в базу данных.
  • Consumer Group: Группа консьюмеров, совместно обрабатывающих сообщения из топика; каждая партиция читается только одним консьюмером из группы, что обеспечивает параллелизм.

Практические аспекты проектирования

При проектировании необходимо решить несколько важных задач:

  • Структура сообщения: Сообщение должно содержать все необходимые данные о чеке (ID заказа, сумма, пользователь, товары) в формате JSON или Avro.
  • Гарантии доставки: Настройка продюсера на подтверждение записи (acks=all) гарантирует, что сообщение будет записано во все реплики партиции перед получением ответа.
  • Идемпотентность: Включение идемпотентности продюсера (enable.idempotence=true) предотвращает дублирование сообщений при повторных отправках из-за сетевых ошибок.
  • Ключ партиционирования: Выбор ключа (например, ID пользователя или заказа) определяет, в какую партицию попадёт сообщение. Сообщения с одинаковым ключом попадают в одну партицию, сохраняя порядок их обработки для этого ключа.

Пример кода продюсера (Node.js)

const { Kafka } = require('kafkajs');

const kafka = new Kafka({
  clientId: 'receipt-service',
  brokers: ['kafka1:9092', 'kafka2:9092']
});

const producer = kafka.producer();

async function sendReceiptEvent(orderId, userId, amount) {
  await producer.connect();
  const message = {
    key: orderId, // Ключ для партиционирования
    value: JSON.stringify({
      eventId: uuidv4(),
      orderId,
      userId,
      amount,
      timestamp: new Date().toISOString()
    })
  };
  // Отправка в топик 'purchase-receipts'
  await producer.send({
    topic: 'purchase-receipts',
    messages: [message]
  });
  console.log(`Receipt event sent for order ${orderId}`);
  await producer.disconnect();
}

Обработка в консьюмере

Консьюмер должен быть готов к обработке ошибок и гарантировать хотя бы однократную доставку. Важно фиксировать оффсет только после успешной обработки сообщения.

const consumer = kafka.consumer({ groupId: 'email-notification-group' });

await consumer.connect();
await consumer.subscribe({ topic: 'purchase-receipts', fromBeginning: false });

await consumer.run({
  eachMessage: async ({ topic, partition, message }) => {
    try {
      const receipt = JSON.parse(message.value.toString());
      // Бизнес-логика: отправка email
      await sendReceiptEmail(receipt.userId, receipt);
      // Оффсет будет зафиксирован автоматически после успешного выполнения
    } catch (error) {
      // Логирование ошибки и отправка сообщения в Dead Letter Queue (DLQ)
      console.error('Failed to process receipt:', error);
      // Важно не фиксировать оффсет, чтобы повторить попытку
    }
  },
});

Вывод: Использование Kafka для системы отправки событий идеально подходит для сценариев, требующих высокой пропускной способности, отказоустойчивости и слабой связанности между сервисами, таких как обработка финансовых транзакций, логов или уведомлений.

Уровень

  • Рейтинг:

    4

  • Сложность:

    7

Навыки

  • Node.js

    Node.js

  • Kafka

    Kafka

Ключевые слова

#Apache Kafka

#event-driven architecture

#message broker

#producer

#consumer

#idempotency

Подпишись на Java Developer в телеграм