我在我的框架中使用Kafka生产者 - 消费者模型。消费者端消耗的记录随后被索引到elasticsearch上。在这里我有一个用例,如果ES关闭,我将不得不暂停kafka消费者,直到ES启动,一旦启动,我需要恢复消费者并消耗我上次离开的记录。 我不认为这可以用@KafkaListener实现。有人可以给我一个解决方案吗?我发现我需要为此编写自己的KafkaListenerContainer,但我无法正确实现它。任何帮助将不胜感激。
答案 0 :(得分:0)
有可能的sevaral解决方案,一种简单的方法是使用KafkaConsumer API。在KafkaConsumer中,实现跟踪主题上的位置,该位置将在下次调用poll(...)时检索。您的问题是在您从Kafka获取记录后,您可能无法将其插入弹性搜索。在这种情况下,您必须编写一个例程来重置使用者的位置,在您的情况下将是consumer.seek(partition,consumer.position(partition)-1)。这会将位置重置为较早的位置。此时,一个好方法是暂停分区(这将使服务器能够进行一些资源清理),然后轮询ES(通过您想要的任何机制)。一旦ES可用,请在消费者处调用resume,并继续进行常规的poll-insert循环。
讨论后编辑
使用指定的生命周期方法创建一个spring bean。在bean的初始化方法中实例化您的KafkaConsumer(从任何源检索使用者的配置)。从该方法开始一个线程与消费者交互并更新ES,其余的设计如上所述。这是一个单一的模型。为了获得更高的吞吐量,请考虑将从Kafka检索到的数据保存在内存中的小队列和调度程序线程中以获取消息并将其提供给池化线程以更新ES。
答案 1 :(得分:0)
我建议相当暂停消费者,为什么不能一次又一次地重试相同的消息,并在消息成功使用后提交偏移量。
例如:
使用@Retryable
使用try / catch阻止你的方法并在catch块中抛出新的异常。
对于ListenerFactory配置,添加属性:
factory.getContainerProperties().setAckMode(AckMode.MANUAL_IMMEDIATE);
factory.getContainerProperties().setAckOnError(false);