kafka new producer无法在其中一个代理关闭后更新元数据

时间:2016-02-29 16:43:47

标签: apache-kafka kafka-producer-api

我有一个kafka环境,有2个经纪人和1个动物园管理员。

当我尝试向kafka发送消息时,如果我停止代理1(这是领导者1),客户端会停止生成消息并给我以下错误,尽管代理2被选为该主题的新领导者partions。

org.apache.kafka.common.errors.TimeoutException:60000毫秒后无法更新元数据。

经过10分钟后,由于经纪人2是新的领导者,我希望生产者向经纪人2发送数据,但是由于给出了上述异常,它继续失败。 lastRefreshMs和lastSuccessfullRefreshMs仍然相同,尽管metadataExpireMs对于制作人来说是300000。

我在生产者方面使用kafka new Producer实现。

似乎在生成器启动时,它会绑定到一个代理,如果该代理发生故障,它甚至不会尝试连接到集群中的另一个代理。

但我的期望是,如果经纪人倒闭,它应该直接检查可用的其他经纪人的元数据并向他们发送数据。

顺便说一下,我的主题是4分区,复制因子为2.给出这些信息以防万一。

配置参数。

{request.timeout.ms=30000, retry.backoff.ms=100, buffer.memory=33554432, ssl.truststore.password=null, batch.size=16384, ssl.keymanager.algorithm=SunX509, receive.buffer.bytes=32768, ssl.cipher.suites=null, ssl.key.password=null, sasl.kerberos.ticket.renew.jitter=0.05, ssl.provider=null, sasl.kerberos.service.name=null, max.in.flight.requests.per.connection=5, sasl.kerberos.ticket.renew.window.factor=0.8, bootstrap.servers=[10.201.83.166:9500, 10.201.83.167:9500], client.id=rest-interface, max.request.size=1048576, acks=1, linger.ms=0, sasl.kerberos.kinit.cmd=/usr/bin/kinit, ssl.enabled.protocols=[TLSv1.2, TLSv1.1, TLSv1], metadata.fetch.timeout.ms=60000, ssl.endpoint.identification.algorithm=null, ssl.keystore.location=null, value.serializer=class org.apache.kafka.common.serialization.ByteArraySerializer, ssl.truststore.location=null, ssl.keystore.password=null, key.serializer=class org.apache.kafka.common.serialization.ByteArraySerializer, block.on.buffer.full=false, metrics.sample.window.ms=30000, metadata.max.age.ms=300000, security.protocol=PLAINTEXT, ssl.protocol=TLS, sasl.kerberos.min.time.before.relogin=60000, timeout.ms=30000, connections.max.idle.ms=540000, ssl.trustmanager.algorithm=PKIX, metric.reporters=[], compression.type=none, ssl.truststore.type=JKS, max.block.ms=60000, retries=0, send.buffer.bytes=131072, partitioner.class=class org.apache.kafka.clients.producer.internals.DefaultPartitioner, reconnect.backoff.ms=50, metrics.num.samples=2, ssl.keystore.type=JKS}

用例:

1-启动BR1和BR2生成数据(Leader为BR1)

2-停止BR2产生数据(罚款)

3-停止BR1(这意味着此时集群中没有活动的工作代理),然后启动BR2并生成数据(尽管领导者是BR2但是失败)

4-启动BR1生成数据(领导者仍然是BR2,但数据是精细生成的)

5-停止BR2(现在BR1是领导者)

6-停止BR1(BR1仍是领导者)

7-启动BR1生成数据(消息再次生成)

如果生产商将最新的成功数据发送给BR1,然后所有经纪人都下降,那么生产商预计BR1会再次起来,尽管BR2已经上升并且是新的领导者。这是预期的行为吗?

3 个答案:

答案 0 :(得分:7)

花了好几个小时后,我在我的情况下想出了卡夫卡的行为。可能是这是一个错误,或者可能是这个需要以这种方式完成,原因在于引擎盖下但实际上如果我会做这样的实现我不会这样做:)

当所有经纪人都倒闭时,如果你只能起床一个经纪人,那么这个经纪人必须是最后才能成功生成消息的经纪人。

假设你有5个经纪人; BR1,BR2,BR3,BR4和BR5。如果一切都失败了,如果最后死亡的经纪人是BR3(这是最后一位领导者),虽然你启动所有经纪人BR1,BR2,BR4和BR5,除非你启动BR3,否则没有任何意义。

答案 1 :(得分:2)

您需要增加重试次数。 在您的情况下,您需要将其设置为> = 5。

这是您的制作人知道您的群集有新领导者的唯一方法。

除此之外,请确保您的所有经纪人都拥有您的分区副本。否则你不会得到一个新的领导者。

答案 2 :(得分:0)

在最新的kafka版本中,当一个代理关闭时,该代理具有生产者使用的领导者分区。生产者将重试,直到捕获可重试的异常为止,然后生产者需要更新元数据。可以从minimumLoadNode获取新的元数据。因此,新负责人将得到更新,制作人可以在此处写信。