[英]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.