元数据
生产者发消息给Kafka,是需要知道Kafka的ip、端口等节点信息,这些节点信息是元数据的一部分,属于元数据Metadata的Cluster的一部分。
我们每一个topic,在Kafka是分布式的形式存放的,所以一个topic就会有多个分区,每个分区对应值着不同的ip、端口等信息。所以每个topic有多少分分区,每个分区的leader节点replica节点的ip、端口信息等,也属于元数据Metadata的Cluster的一部分。
对于生产者客户端来说,这些元数据都是Kafka的信息,所以往kafka发送消息之前,就需要拉取元数据。
初始化
Metadata是KafkaProducer的一个属性,在KafkaProducer初始化的时候,也会实例化一个Metadata对象,可能有人觉得,实例化Metadata后,就会去拉取元数据信息。
但是kafka并没有这么做,只是对集群元数据做了一个初始化,我们在上一篇已经知道KafkaProducer是有配置bootstrap.servers
这个属性的。所以初始化的时候,就是把配置的地址,转换为Node,Node就存储着配置的ip和port,放在Cluster对象实例里,上面已经说过,Cluster对象也是Metadata的属性。由于bootstrap.servers
是可以配置多个的,所以在Cluster中存储的是Node列表。
所以KafkaProducer初始化的时候并没有加载元数据的,这是懒加载的编程思想。
发送时
在元数据里,我们已经看到Metadata的cluster存放topic相关的信息,如果发送的时候,发现这个topic在cluster中并没有对应的信息,那就需要去拉取元数据信息。
默认情况下,我们只拉取自己要发送消息的对应的topic的元数据的信息,并不会拉取所有的元数据信息,所以在初始化的时候,并不会拉取元数据,因为那时候,根本不知道生产者需要发送哪些topic。
等到下一次往这个topic发送数据的时候,直接就会从Metadata的cluster中拿数据。
某个时机
Metadata在实例化的时候,会有两个构造参数,一个读取配置config里的metadata.max.age.ms
信息,默认是5分钟,这个作用是,距离上次成功拉取的时间超过5分钟会刷新一下。
另外一个参数读取配置config里的retry.backoff.ms
信息,默认100ms,这个作用是,距离上一次更新元数据的时间跟当前时间对比,如果还没有到100ms,那就不能更新元数据,避免频繁更新。注意这里只是和上次更新的时间比较,并不是成功拉取的时间。
如果有一个拉取元数据的任务了,那就不能继续去拉取元数据。
对于能不能拉取元数据,主要还是看上面三种情况。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。