Kafka Consumer在处理消息时重试次数有限

时间:2018-04-28 07:15:53

标签: apache-kafka kafka-consumer-api

我很难在Kafka主题的消费者中找到处理异常的简单模式。 场景如下:在消费者中我称之为外部服务。如果服务不可用,我想重试几次,然后停止消费。

最简单的模式似乎是一种阻塞同步的处理方式,在java中是这样的:

ConsumerRecords<String, String> records = consumer.poll(100);
for (ConsumerRecord<String, String> record : records) {
    boolean processed=false;
    int count=0;
    while (!processed) {
        try {
            callService(..); 
        } catch (Exception e) {
            if (count++ < 3) {
                Thread.sleep(5000);
                continue;
            } else throw new RuntimeException();
        }
    }
}

但是,我觉得必须有一个更简单的方法(不使用第三方库),以及避免阻塞线程的方法。

似乎我们希望拥有一个常见的东西,但我找不到这个模式的简单示例。

1 个答案:

答案 0 :(得分:1)

Kafka没有开箱即用的重审机制。有了使用RabbitMQ的经验,MQ提供了重试交换。这些交换在RabbitMQ中称为Dead-Letter-Exchanges

https://www.rabbitmq.com/dlx.html

对于kafka,您可以应用相同的模式。

在消息处理失败时,我们可以将消息的副本发布到另一个主题并等待下一条消息。我们将新主题称为“retry_topic”。 'retry_topic'的消费者将从Kafka接收消息,然后在开始消息处理之前等待一些预定义的时间,例如一小时。通过这种方式,我们可以推迟下一次消息处理尝试,而不会对'main_topic'消费者产生任何影响。如果'retry_topic'消费者中的处理失败,我们只需放弃并将消息存储在'failed_topic'中,以便进一步手动处理此问题。 'main_topic'消费者代码可能如下所示:

在失败/异常时将消息推送到retry_topic

void consumeMainTopicWithPostponedRetry() {
    while (true) {
        Message message = takeNextMessage("main_topic");
        try {
            process(message);
        } catch (Exception ex) {
            publishTo("retry_topic");
            LOGGER.warn("Message processing failure. Will try once again in the future.", ex);
        }
    }
}

重试主题的消费者

void consumeRetryTopic() {
    while (true) {
        Message message = takeNextMessage("retry_topic");
        try {
            process(message);
            waitSomeLongerTime();
        } catch (Exception ex) {
            publishTo("failed_topic");
            LOGGER.warn("Message processing failure. Will skip it.", ex);
        }
    }
}

上述策略和示例摘自以下链接。整个功劳归功于博文的所有者。 https://blog.pragmatists.com/retrying-consumer-architecture-in-the-apache-kafka-939ac4cb851a

通过阅读整篇博文,可以理解上面做的非阻塞方式。希望这会有所帮助。