Код-ревью Senior Kafka в Spring обновлено
Код-ревью: обработка платежей из Kafka
Вопрос
Найдите проблемы в продюсере и потребителе.
@Service
public class PaymentEvents {
private final KafkaTemplate<String, PaymentEvent> kafka;
private final PaymentRepository repo;
private final RestClient bank;
public PaymentEvents(KafkaTemplate<String, PaymentEvent> kafka,
PaymentRepository repo, RestClient bank) {
this.kafka = kafka;
this.repo = repo;
this.bank = bank;
}
@Transactional
public void pay(Payment p) {
repo.save(p);
kafka.send("payments", UUID.randomUUID().toString(), new PaymentEvent(p.getId()));
}
@KafkaListener(topics = "payments", groupId = "ledger", concurrency = "12")
public void onPayment(PaymentEvent e) {
repo.insertLedgerEntry(e.paymentId());
bank.post().uri("/notify").body(e).retrieve().toBodilessEntity();
}
}
Коротко
Надёжная интеграция с Kafka держится на трёх вещах: событие публикуется вместе с данными (outbox), ключ сохраняет порядок по сущности, потребитель идемпотентен и имеет обработку ошибок с ограниченными повторами и DLT.
Что должен найти ревьюер
- Ошибкастрока 17Отправка в Kafka внутри транзакции до коммита: при откате событие уже ушло, а при падении после коммита оно может потеряться. Нужен outbox или отправка после коммита.
- Ошибкастрока 17Случайный ключ: события одного платежа попадут в разные партиции, порядок не гарантирован. Ключом должен быть id платежа.
- Ошибкастрока 17Результат send игнорируется: ошибка асинхронной отправки останется незамеченной.
- Производительностьстрока 20concurrency = 12 бессмысленна, если у топика меньше партиций: лишние потоки простаивают.
- Ошибкастрока 22Неидемпотентная вставка в журнал: при повторной доставке (at-least-once) запись задвоится. Нужна проверка id сообщения или upsert.
- Ошибкастрока 23Внешний HTTP-вызов в слушателе без таймаута и обработки ошибок: при сбое банка сообщение ретраится вместе с уже сделанной вставкой, партиция блокируется. Нужен DefaultErrorHandler с DLT и идемпотентность.
Разбор
Надёжная интеграция с Kafka держится на трёх вещах: событие публикуется вместе с данными (outbox), ключ сохраняет порядок по сущности, потребитель идемпотентен и имеет обработку ошибок с ограниченными повторами и DLT.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.