简体   繁体   English

由于 kafka 流存储正在等待运行,应用程序无法启动

[英]Application fails to start due to kafka streams store is waiting to be running

I have a spring boot application working with kafka streams (kafka docker image: wurstmeister/kafka:2.12-2.1.1 , kafka dependencies: org.apache.kafka:kafka-streams:2.4.1 ). I have a spring boot application working with kafka streams (kafka docker image: wurstmeister/kafka:2.12-2.1.1 , kafka dependencies: org.apache.kafka:kafka-streams:2.4.1 ). During application start up I check whether or not topic my-topic is created, if not - application creates it.在应用程序启动期间,我检查是否创建了主题 my-topic,如果没有 - 应用程序创建它。 After that application creates KTable like:在该应用程序创建KTable之后,如下所示:

streamsBuilder.table("my-topic", Consumed.with(Serdes.String(), Serdes.String()), Materialized.as("my-topic-store"))

And further, I create store in order to query it:此外,我创建商店以查询它:

while(true)
    try{
        return kafkaStreams.store("my-topic-store", QueryableStoreTypes.keyValueStore()) 
    } catch (InvalidStateStoreException e) {
        log.info("Waiting for store {} is RUNNING", "my-topic-store");
        Thread.sleep(1000);
    }
}

My application is deployed in k8s.我的应用程序部署在 k8s 中。 When new version of application is ready, k8s starts new application and scales down old one.当新版本的应用程序准备好时,k8s 会启动新的应用程序并缩减旧的应用程序。 The problem is when new application starts up, I see in logs only multiple lines like: "Waiting for store my-topic-store is RUNNING.问题是当新应用程序启动时,我在日志中只看到多行,例如:“Waiting for store my-topic-store is RUNNING。

I tried to dig into the problem.我试图深入研究这个问题。 From kafka documentation, 1 partition is read by only 1 consumer, and 1 consumer can read from multiple partitions.从kafka文档看,1个partition只能被1个consumer读取,1个consumer可以读取多个partition。 If new consumer comes and all partitions already 'occupied', this consumer becomes idle.如果新的消费者来了并且所有的分区都已经被“占用”了,这个消费者就会变得空闲。 In our case, when new application starts up, means new consumer is coming, it becomes idle because old application with old consumers is still working, therefore new consumer is not able to listen kafka partition.在我们的例子中,当新应用启动时,意味着新消费者来了,它变得空闲,因为旧消费者的旧应用仍在工作,因此新消费者无法监听 kafka 分区。 I should notice, that application is configured with 5 threads for kafka streams, and there are 23 topics at all each of them with 1 partition (I tried to change partition number from 1 to 5, but it did not help).我应该注意到,该应用程序为 kafka 流配置了 5 个线程,并且每个主题都有 23 个主题,每个主题都有 1 个分区(我试图将分区号从 1 更改为 5,但没有帮助)。 Application redeployment is happened with no load at all.应用程序重新部署是在没有负载的情况下发生的。

What you describe (in the comment) is expected behavior.您所描述的(在评论中)是预期的行为。

When you start the new app, it will join the consumer group.当您启动新应用程序时,它将加入消费者组。 Because there is only one partition, the new app does not get any work assigned (there is no reason to re-assign work because it would just be an expensive state migration; note that from a rebalancing point of view, you application scaled out; it's unknown that you plan to stop the already existing app).因为只有一个分区,新应用程序没有分配任何工作(没有理由重新分配工作,因为这只是一个昂贵的 state 迁移;请注意,从重新平衡的角度来看,您的应用程序横向扩展了;不知道您打算停止已经存在的应用程序)。

When you finally stop the old app, work (and state) is reassigned.当您最终停止旧应用程序时,会重新分配工作(和状态)。

Also note that starting a new instance would never stop any existing instance.另请注意,启动新实例永远不会停止任何现有实例。 Instead, as mentioned already, it's considered a scale out of your application.相反,如前所述,它被视为您的应用程序的扩展。

The recommended way to upgrade an application is to stop the old instance first, and restart the new instance on the same server so it can pick up the state from the old instance from disk.升级应用程序的推荐方法是先停止旧实例,然后在同一台服务器上重新启动新实例,以便它可以从磁盘上的旧实例中获取 state。 This avoids expensive state migration.这避免了昂贵的 state 迁移。

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

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