Вопрос проверяет умение проектировать отказоустойчивые асинхронные системы обработки событий с использованием Apache Kafka, что необходимо для построения масштабируемых микросервисных архитектур.
Проектирование системы отправки событий, такой как чеки, с использованием Apache Kafka, требует понимания её роли как распределённого лога сообщений. Основная цель — обеспечить надёжную, масштабируемую и отказоустойчивую передачу данных между различными частями системы (микросервисами).
Архитектура строится на нескольких основных концепциях Kafka:
purchase-receipts. Топики делятся на партиции для горизонтального масштабирования.При проектировании необходимо решить несколько важных задач:
acks=all) гарантирует, что сообщение будет записано во все реплики партиции перед получением ответа.enable.idempotence=true) предотвращает дублирование сообщений при повторных отправках из-за сетевых ошибок.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 для системы отправки событий идеально подходит для сценариев, требующих высокой пропускной способности, отказоустойчивости и слабой связанности между сервисами, таких как обработка финансовых транзакций, логов или уведомлений.