Kafka尝试以“恢复模式”将消息发送给代理

时间:2019-08-09 13:28:01

标签: apache-kafka spring-kafka kafka-producer-api

我有以下设置

3个Kafka(v2.1.1)经纪人 5个Zookeeper实例

Kafka经纪人具有以下配置:

      auto.create.topics.enable: 'false'
      default.replication.factor: 1
      delete.topic.enable: 'false'
      log.cleaner.threads: 1
      log.message.format.version: '2.1'
      log.retention.hours: 168
      num.partitions: 1
      offsets.topic.replication.factor: 1
      transaction.state.log.min.isr: '2'
      transaction.state.log.replication.factor: '3'
      zookeeper.connection.timeout.ms: 10000
      zookeeper.session.timeout.ms: 10000
      min.insync.replicas: '2'
      request.timeout.ms: 30000

生产者配置(使用Spring Kafka)或多或少如下:

...
acks: all
retries: Integer.MAX_VALUE
deployment.timeout.ms: 360000ms
enable.idempotence: true
...

我的配置如下:有3个Kafka代理,但是一旦其中一个代理死亡,最好是至少有两个在发送回送确认之前复制并保留数据(=同步副本)。如果发生故障,Kafka生产者将继续重试6分钟,然后放弃。

这是使我头疼的情况:

  • 所有Kafka和Zookeeper实例均已启动并处于活动状态
  • 我开始分块发送消息(每个发送500个)
  • 在处理过程中,其中一位经纪人死亡(强行杀死)
  • 我立即看到2019-08-09 13:06:39.805 WARN 1 --- [b6b45bb5c-7dxh7] o.a.k.c.NetworkClient : [Producer clientId=bla-6b6b45bb5c-7dxh7, transactionalId=bla-6b6b45bb5c-7dxh70] 4 partitions have leader brokers without a matching listener, including [...] 之类的日志(问题1:我看不到任何其他消息,这是否真的意味着整个集群现在都卡住了,等待死掉的Broker返回???)
  • 已终止的Broker重新启动后,从恢复已损坏的索引开始。由于我在Kafka集群上有很多数据,因此此操作需要10分钟以上的时间。
  • 每隔30秒,生产者就会尝试再次发送消息(由于request.timeout.ms属性设置为30s)
  • 由于我的deployment.timeout.ms大约需要6分钟,并且Broker需要10分钟才能恢复并且在此之前不保留数据,因此生产者放弃并停止重试=我有可能丢失数据

问题是

  • 为什么Kafka集群要等到死去的Broker回来?
  • 当生产者意识到代理没有响应时,为什么它不尝试连接另一个代理?
  • 线程完全卡住了6分钟,等到死掉的Broker恢复后,我如何告诉生产者宁可尝试另一个Broker?
  • 我错过了什么吗?还是有什么好的做法来避免这种情况?

1 个答案:

答案 0 :(得分:0)

您有很多问题,我将提供一些经验,希望能对其中的一些问题有所启发。

在我的产品IBM IDR Replication中,我们必须为正在重新平衡主题或在集群中失去经纪人的客户提供增强鲁棒性的信息。我们测试的结果是,仅设置请求超时是不够的,因为在某些情况下,请求将决定不等待整个时间,而是几乎立即执行另一个重试。这烧毁了配置的重试次数Ie。在某些情况下可以避开超时期限。

因此,我们指示用户使用类似以下的公式...

https://www.ibm.com/support/knowledgecenter/en/SSTRGZ_11.4.0/com.ibm.cdcdoc.cdckafka.doc/tasks/robust.html

“要调整环境的值,请根据以下公式调整Kafka生产者属性retry.backoff.ms并重试: retry.backoff.ms *重试>领导者变更元数据在clusterCopy中传播的预期最大时间 例如,您可能希望配置retry.backoff.ms = 300,retries = 150和max.in.flight.requests.per.connection = 1。”

因此,请尝试使用重试和retry.backoff.ms。请注意,如果您有多个在飞行中,那么使用没有幂等性的重试可能导致批次被乱写...因此请根据您的业务逻辑进行相应选择。

根据我们的经验,卡夫卡制片人写信给该主题的负责人经纪人,因此您必须等待新的负责人被选出。在这种情况下,如果重试过程仍在进行,则生产者将透明地确定新的领导者并相应地写入数据。