我有一组作为集群运行的Kafka代理实例。我有一个向Kafka提供数据的客户端:
props.put("metadata.broker.list", "broker1:9092,broker2:9092,broker3:9092");
当我们使用tcpdump进行监控时,我可以看到只有与broker1和broker2的连接是ESTABLISHED,而对于broker3,我的生产者没有连接。我只用一个分区就有一个主题。
我的问题:
经纪人数与主题分区之间的关系如何?我应该总是有经纪人数=分数数吗?
为什么在我的情况下,我无法连接到broker3?或至少我的网络监控没有显示我的生产者与broker3建立的连接?
如果能够从制片人的立场深入了解与经纪人的联系是如何工作的话,那就太棒了。
答案 0 :(得分:22)
显然,您的制作人不需要连接到broker3
:)
我将尝试向您解释当您向Kafka生成数据时会发生什么:
foo
,复制因子2.非常简单的例子,但可能是某人的真实案例。metadata.broker.list
(或新生产者中为bootstrap.servers
)的生产者。值得一提的是,您不一定要指定群集中的所有代理,实际上您只能指定其中的一个代理,它仍然可以工作。我也会解释一下。foo
发送消息。foo
的每个分区的领导者,以及您的foo
主题有多少分区。由于这是第一次发送给生产者,因此本地缓存不包含任何内容。TopicMetadataRequest
中的每个代理发送metadata.broker.list
,直到第一次成功响应。这就是为什么我提到该列表中的1个经纪人只要活着就会工作。TopicMetadataResponse
将包含有关所请求主题的信息,在您的情况下,它是foo
和群集中的代理。基本上,此响应包含以下内容:
TopicMetadataResponse
生产者构建其本地缓存,现在确切地知道主题foo
分区0
的请求应该转到代理X. linger.ms
时,生产者将批处理刷新到代理。通过“刷新”我的意思是“打开与代理的新连接或重用现有代理,并发送ProduceRequest
”。生产者不需要打开与所有代理的不必要的连接,因为您生成的主题可能无法由某些代理提供服务,并且您的群集可能非常大。想象一下1000个代理群集有很多主题,但其中一个主题只有一个分区 - 你只需要一个连接,而不是1000个。
在您的特定情况下,如果您只有一个分区,我不能100%确定为什么您有两个与代理的开放连接,但我假设在元数据发现期间打开了一个连接并且缓存以便重用,第二个一个是生成数据的实际代理连接。但是,在这种情况下我可能错了。
但无论如何,根本没有必要为第三个经纪人建立连接。
关于“我是否应该总是拥有经纪人数量=分数?”的问题。答案很可能是没有。如果你解释一下你想要实现的目标,也许我能够指出你正确的方向,但这一点太宽泛而无法解释。我建议您阅读this来澄清事情。
UPD回答评论中的问题:
元数据缓存更新有两种情况:
如果生产者因任何原因无法与代理通信 - 这包括代理根本无法访问且代理响应错误的情况(例如“我不再是该分区的领导者”,请执行程“)
如果没有发生任何故障,客户端仍会每metadata.max.age.ms
(https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/clients/CommonClientConfigs.java#L42-L43)刷新一次元数据,以发现新的代理和分区本身。