Kafka在Kubernetes上流:重新部署后长期重新平衡

时间:2020-05-08 12:33:49

标签: java kubernetes apache-kafka apache-kafka-streams

问题

我们使用StatefulSet在Kubernetes上部署Scala Kafka Streams应用程序。实例具有单独的applicationId,因此它们每个都复制完整的输入主题以实现容错。它们本质上是只读服务,仅读取状态主题并将其写入状态存储,在该状态存储中通过REST服务客户请求。这意味着,在任何给定时间,消费者组始终仅包含一个单个Kafka Streams实例

现在的问题是,触发滚动重启时,每个实例大约需要5分钟才能启动,其中大部分时间都花在了REBALANCING状态下。我已经读过here,Kafka Streams不会发送LeaveGroup请求,以便在容器重新启动后快速返回而无需重新平衡。为什么这对我们不起作用?为何即使applicationId相同,重新平衡也要花这么长时间?理想情况下,为了最大程度地减少停机时间,应用程序应立即从重新启动时离开的位置开始接管。

配置

以下是一些我们从默认值更改的配置:

properties.put(StreamsConfig.consumerPrefix(ConsumerConfig.MAX_POLL_RECORDS_CONFIG), "1000")
properties.put(StreamsConfig.consumerPrefix(ConsumerConfig.SESSION_TIMEOUT_MS_CONFIG), "300000")
properties.put(StreamsConfig.consumerPrefix(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG), "earliest")
// RocksDB config, see https://docs.confluent.io/current/streams/developer-guide/memory-mgmt.html
properties.put(StreamsConfig.ROCKSDB_CONFIG_SETTER_CLASS_CONFIG, classOf[BoundedMemoryRocksDBConfig])    

问题/相关配置

  • 减少session.timeout.ms会有所帮助吗?我们将其设置为相当大的价值,因为Kafka经纪人居住在不同的数据中心中,并且网络连接有时也不是非常可靠。
  • This answer建议减少max.poll.interval.ms,因为它与重新平衡超时有关。那是对的吗?我不愿意更改此设置,因为它可能会影响我们应用的正常运行模式。
  • There is mention的配置group.initial.rebalance.delay.ms会延迟部署期间的重新平衡-但这也会导致从崩溃中恢复后的延迟,不是吗?
  • 我还偶然发现KIP-345,该目标旨在完全通过group.instance.id消除消费者对静态成员资格的重新平衡,这很适合我们的用户情况,但似乎尚不可用在我们的经纪人上。

我对众多配置以及如何使用它们在更新后实现快速恢复感到困惑。有人可以解释他们如何一起玩吗?

1 个答案:

答案 0 :(得分:2)

您引用的另一个问题并不表示在重新启动时避免了重新平衡。不发送LeaveGroupRequest仅在停止应用程序时避免重新平衡。因此,重新平衡的次数从两个减少到一个。当然,对于您有些不寻常的单实例部署,您在这里什么也得不到(实际上,它实际上可能会“伤害”您...)a

减少session.timeout.ms是否有帮助?我们将其设置为一个很大的值,因为Kafka经纪人居住在不同的数据中心中,并且网络连接有时也不是非常可靠。

可能取决于您重新启动应用程序的速度。 (下面有更多详细信息。)也许只是尝试一下(即,将其设置为3分钟以保持较高的稳定性,然后将其重新平衡时间降至3分钟?

此答案建议减少max.poll.interval.ms,因为它与重新平衡超时有关。那是对的吗?我不愿意更改此设置,因为它可能会影响我们应用的正常运行模式。

max.poll.interval.ms也影响重新平衡时间(下面有更多详细信息)。但是,默认值为30秒,因此不应导致5分钟的重新平衡时间。

这里提到了一个配置group.initial.rebalance.delay.ms来延迟部署期间的重新平衡-但这也会在崩溃恢复后引起延迟,不是吗?

这仅适用于空的使用者组,默认值为3秒。因此它不会影响您。

我还偶然发现了KIP-345,它的目标是完全通过group.instance.id消除消费者对静态成员资格的重新平衡,这很适合我们的用户情况,但似乎在我们的产品上尚不可用经纪人。

使用静态组成员身份实际上可能是最好的选择。也许值得升级您的经纪人以获得此功能。

顺便说一句,session.timeout.msmax.poll.interval.ms之间的区别在另一个问题中得到了解释:Difference between session.timeout.ms and max.poll.interval.ms for Kafka 0.10.0.0 and later versions

通常,代理方组协调器维护每个“组生成”的所有成员的列表。如果成员主动(通过发送LeaveGroupRequest)离开组,超时(通过session.timeout.msmax.poll.interval.ms)或新成员加入组,则会触发重新平衡。如果发生重新平衡,每个成员都有机会重新加入该小组,以纳入下一代。

对于您而言,该组只有一名成员。当您停止应用程序时,不会发送任何LeaveGroupRequest,因此组协调员只有在session.timeout.ms通过之后才能删除该成员。

如果重新启动该应用程序,则该应用程序将作为“新”成员回来(从组协调者的角度来看)。这将触发重新平衡,使组中的所有成员都可以更改以重新加入该组。对于您的情况,“旧”实例可能仍在组中,因此,只有在组协调员从组中删除旧成员之后,重新平衡才能继续进行。问题可能是,组协调员认为该组从一个成员扩展到两个成员...(这就是我上面的意思:如果发送LeaveGroupRequest,则当您停止您的应用,然后在重新启动时只有新成员进入该组,并且重新平衡会立即进行。)

使用静态组成员身份可以避免该问题,因为在重新启动后,该实例可以重新标识为“旧”实例,并且组协调器不需要等待使旧组成员过期。