卡夫卡消费者中死信队列的最佳选择是什么

时间:2019-10-05 11:44:31

标签: spring apache-kafka kafka-consumer-api spring-kafka dead-letter

我正在写一个卡夫卡消费者。使用者的工作主要是创建多个数据库实体,并在处理有效负载后保存它们。我正在尝试编写代码来处理在使用数据时可能发生的错误。 为此,我可以想到两种选择(在春季生态系统中)

  1. 将失败的消息发送到一个死信kafka主题
  2. 将失败的消息发送到新的数据库表(错误表)

失败的消息需要再次处理。

在案例1中: 再次,我必须编写另一个@KafkaListner,它监听死信主题并处理消息。这里的问题是我无法控制如何启动重新处理流程。 (就像调度程序一样),因为KafkaListener会在死信主题中发布数据后立即开始处理数据。

在情况2中: 由于我可以编写REST端点或计划程序来尝试重新处理失败的消息,因此我对重新处理流程有更多控制权。 (这里我对使用哪个数据库感到困惑。关系式或一些键值存储)

我基本上遇到了设计难题,无法确定哪种方法在Spring生态系统中更好。

感谢您的答复。

2 个答案:

答案 0 :(得分:0)

我认为使用Kafka是最好的解决方案。

  

因为KafkaListener将在死信主题中发布数据后立即开始处理数据。

您可以通过在该侦听器上将autoStartup设置为false来控制行为,然后根据需要使用KafkaListenerEndpointRegistry启动/停止侦听器:

registry.getListenerContainer(myListenerId).start();

或者,您可以使用自己的KafkaConsumer(由消费者工厂创建)并轮询所需数量的记录,并在完成后关闭消费者。

答案 1 :(得分:0)

我同意Gary Russell的回答,您可以创建KafkaConsumer实例并控制其生命周期。该类来自org.apache.kafka:kafka-clients库。

在特定情况下,您可以添加Thread.sleep(schedulerDelay)来实现计划。这是简化的示例:

@Component
class Scheduler() {

  public void init() {
    // create kafka consumer connected to your DLQ topic
  }

  public void run() {
    try {
      while (running) {
        ConsumerRecords<String, String> records = consumer.poll(1000);
        for (ConsumerRecord<String, String> record : records)
          processRecordLogicGoesHere(record);
        Thread.sleep(schedulerDelay);
      }
    } finally {
      consumer.close();
    }
  }

}

schedulerDelay应该被小心地拾取,以跟上传入的消息,并且不要让它们因Kafka的日志清理策略而丢失。

关于如何使用Kafka的官方API的教程很多,这里是其中之一:Introducing the Kafka Consumer

此外,您可能会在这里找到一些想法:Retrying consumer architecture in the Apache Kafka