Apache kafka 处理消息时重试次数有限的Kafka消费者

Apache kafka 处理消息时重试次数有限的Kafka消费者,apache-kafka,kafka-consumer-api,Apache Kafka,Kafka Consumer Api,我很难在卡夫卡主题的使用者中找到处理异常的简单模式。 场景如下:在消费者中,我调用一个外部服务。如果服务不可用,我想重试几次,然后停止使用 最简单的模式似乎是一种处理它的阻塞同步方式,在java中是这样的: ConsumerRecords<String, String> records = consumer.poll(100); for (ConsumerRecord<String, String> record : records) { boolean proc

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

最简单的模式似乎是一种处理它的阻塞同步方式,在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();
        }
    }
}
ConsumerRecords记录=consumer.poll(100);
对于(消费者记录:记录){
布尔值=假;
整数计数=0;
而(!已处理){
试一试{
呼叫服务(…);
}捕获(例外e){
如果(计数+++<3){
睡眠(5000);
继续;
}否则抛出新的RuntimeException();
}
}
}
但是,我觉得必须有一种更简单的方法(不使用第三方库),并且避免阻塞线程


这似乎是我们想要的一件普通的事情,但我找不到一个简单的例子来说明这种模式

卡夫卡没有现成的重审机制。有使用RabbitMQ的经验,其中MQ提供重试交换。这些交换在RabbitMQ中称为
死信交换

您可以在卡夫卡的案例中应用相同的模式

在消息处理失败时,我们可以将消息的副本发布到另一个主题并等待下一条消息。让我们把这个新主题称为“
重试”\u 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);
        }
    }
}
以上策略和示例摘自以下链接。这一切都归功于博客文章的所有者。


对于以上的非阻塞方式,可以通过阅读整个博客文章来理解。希望这能有所帮助。

如果你想无论如何都继续消费,这似乎是一个可能的解决方案。但我也希望能够停止消费,例如,因为某些后端系统出现故障,您不想重击它。出于同样的原因,我们将创建多个主题,以避免影响数据库。此解决方案将帮助您避免两件事1。每当消息未能持续>2时,重试命中数据库。通过将消息推送到其他队列以供以后使用来跳过消息。我不明白。我们不断地处理来自主要主题的消息。如果后端服务(如DB)失败,则所有消息都将失败,并将全部移动到重试队列。但与此同时,你已经敲打了后端。我希望卡夫卡中的一些内置函数在重试x次后停止使用主主题。有点像断路器。但也许这在卡夫卡中并不存在,我们需要自己构建复杂的逻辑。当DB关闭时,为什么你会觉得自己在敲打。我觉得你把事情搞复杂了。当数据库关闭时,即主机不可用。当您尝试连接数据库时,主机将不可用,因此没有连接到数据库的意义。您可能是对的,尽管关闭的数据库也可能是过载的web服务。然而,在这种情况下,我认为我可以将重试与服务呼叫的断路器结合起来。