繁体   English   中英

如何暂停kafka消费者?

[英]How to pause a kafka consumer?

我在我的框架中使用 Kafka 生产者 - 消费者 model。 在消费者端消费的记录后来被索引到 elasticsearch。这里我有一个用例,如果 ES 关闭,我将不得不暂停 kafka 消费者,直到 ES 启动,一旦启动,我需要恢复消费者并从我上次离开的地方消费记录。 我不认为这可以通过@KafkaListener 实现。 谁能给我一个解决方案? 我发现我需要为此编写自己的 KafkaListenerContainer,但我无法正确实现它。 任何帮助将非常感激。

有几种可能的解决方案,一种简单的方法是使用 KafkaConsumer API。 在 KafkaConsumer 实现中,跟踪将在下一次调用 poll(...) 时检索的主题上的位置。 你的问题是你从Kafka获取记录后,可能无法插入到Elastic Search中。 在这种情况下,您必须编写一个例程来重置消费者的位置,在您的情况下将是 consumer.seek(partition, consumer.position(partition)-1)。 这会将位置重置为较早的位置。 此时,一个好的方法是暂停分区(这将使服务器能够进行一些资源清理),然后轮询 ES(通过您想要的任何机制)。 一旦 ES 可用,在消费者上调用 resume 并继续您通常的轮询-插入循环。

讨论后编辑

使用指定的生命周期方法创建一个 spring bean。 在 bean 的初始化方法中实例化您的 KafkaConsumer(从任何来源检索消费者的配置)。 从方法开始一个线程与消费者交互并更新ES,其余的设计同上。 这是一个单线程模型。 为了获得更高的吞吐量,请考虑将从 Kafka 检索到的数据保留在内存队列中的小内存队列中,并使用一个调度程序线程来获取消息并将其提供给池线程以更新 ES。

我建议暂停 consumer ,为什么你不能一次又一次地重试同一条消息,并在成功消费消息后提交偏移量。

例如:

使用@Retryable注释您的方法

并使用 try/catch 阻止您的方法并在 catch 块中抛出新异常。

对于 ListenerFactory 配置添加属性:

factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
factory.getContainerProperties().setAckOnError(false);
Autowired
private KafkaListenerEndpointRegistry registry;


KafkaListener(id = "dltGroup", topics = "actualTopicNAme.DLT", autoStartup = "false")
public void dltListen(String in) {
    logger.info("Received from DLT: " + in);
}


public void startKafka() {
    // TODO if not running
    registry.getListenerContainer("dltGroup").start();
}

public void resumeKafka() {
    if (registry.getListenerContainer("dltGroup").isContainerPaused() || 
registry.getListenerContainer("dltGroup").isPauseRequested()) {
        registry.getListenerContainer("dltGroup").resume();
    }
}

public void pauseKafka() {
    if (registry.getListenerContainer("dltGroup").isRunning()) {
        registry.getListenerContainer("dltGroup").pause();
    }
}

有几种方法可以实现这一点。

方法#1

在 Thread 中创建KafkaConsumer object 并运行无限while循环来使用事件。

完成此设置后,您可以中断线程并在while循环中检查Thread.interrupt()是否为true 如果是,跳出循环并关闭消费者。

完成恢复活动后,使用相同的组 ID 重新创建消费者。 请注意,这可能会重新平衡消费者。

如果您使用的是 python,则可以使用线程stop_event来实现相同的目的。

方法#2

使用 KafkaConumer API pause(partitions_list) function。它接受 Kafka 分区作为输入。 因此,提取分配给消费者的所有部分,并将这些部分传递给pause(partitions_list) function。消费者将停止从这些分区中提取数据。

一定时间后,可以使用resume(partitions_list) function恢复消费者。 这种方法不会重新平衡消费者。

注意:如果你使用的是Spring Kafka客户端。 这变得容易多了。 您可以启动/停止消息侦听器容器。

您可以在此处找到详细说明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM