版权声明:标明原创的版权均归本人所有,任何人或团体、机构全部转载或者部分转载、摘录,请保留本博客链接或标注来源. https://blog.csdn.net/lt793843439/article/details/89329926
目录
Kafka生产者源码解析之一KafkaProducer
Kafka生产者源码解析之二RecordAccumulator
Kafka生产者源码解析之三NIO
Kafka生产者源码解析之四Sender
Kafka生产者源码解析之五小结
前言
本篇主要把前几篇关于生产者做一个小结,主要以过程描述为主,就不附加代码了。想看代码和解释的同学可以参考下前几篇博客。
其实kafka生产者总结起来就干了两件事,运行了两个线程。
两件事
初始化
其实kafka生产者总结起来就干了两件事,第一件事就是初始化。看下面得实例代码。
ProducerRecord<String,String> record = new ProducerRecord<String, String>(topic,i+"",value);
Producer<String, String> producer = new KafkaProducer<String, String>(props);
producer.send(record,(metadata, exception) ->
System.out.println("message send to partition " + metadata.partition() + ", offset: " + metadata.offset())
);
- 创建一个生产消息记录对象ProducerRecord,此对象里面就包含了主题topic,分区partiton,标题headers,时间戳timestamp,消息记录键key和值value。
- 创建一个生产者对象KafkaProducer,通过配置文件初始化一些参数。
- 生产者构造器里面还创建一个消息累加器对象RecordAccumulator,其构造方法里面创建了一个缓存 池对象BufferPool
- 接着创建了一个Sender线程对象,其构造方法里面创建了一个kafka客户端对象NetworkClient,它实现了KafkaClient接口。
- NetworkClient类的构造器里面创建了一个network.Selector,selector构造器里面打开了一个nio的选择器WindowsSelectorImpl
- 最后通过Sender对象创建了一个KafkaThread线程,启动了KafkaThread线程,即运行了Sender线程的run方法
发送消息
- 消息首先会进入到拦截器ProducerInterceptors集合,默认集合里的拦截器是空,可以自定义拦截器,实现ProducerInterceptor接口即可。
- 记录线程数加一,最后在finally里会减一
- 然后检查主题的元数据,确保可用,获取对应的节点
- 序列化消息的key和value字段
- 创建主题分区对象TopicPartition
- 将消息追加到RecordAccumulator消息累加器中
- 尝试将消息追加到 Deque 双端队列里的 ProducerBatch 批处理对象中。如果返回的结果不为空,则直接返回RecordAppendResult追加结果
- 如果第六步的返回为空,即尝试追加消息失败,则将消息写入内存中,封装成一个 MemoryRecordsBuilder 内存消息对象
- 根据此内存消息对象新建一个批处理对象,并加入到双端队列中。
- 然后将这个批处理对象加入到尚未确认的批处理对象集合中
- 释放buffer缓冲区, 在finally里面将buffer回收到缓冲池里面,记录线程数减一
- 返回RecordAppendResult追加结果
- 最后判断返回结果中的两个标识(存消息的batch缓存满了或者新创建了一个batch),如果为true,则调用Sender线程的wakeup方法,即调用 NIO的选择器
WindowsSelectorImpl 的wakeup方法
两个线程
主线程
- 主线程主要将消息放入NIO的 buffer 中,此 buffer 存在MemoryRecordsBuilder内存消息创建者对象里面的 appendStream 输出流中
- 内存消息创建者对象存放于ProducerBatch批处理对象中
- 批处理对象被添加到Deque双端队列中
Sender线程
- 此线程是在KafkaProducer类的构造器里面被启动的
- Sender线程维护了一个running标识,一直循环调用 NetworkClient 的poll方法
- 启动选择好的节点的连接,比如打开通道,注册到选择器等
- 调用了network.Selector 类的poll方法
- NIO的selector选择通道,返回一组就绪的键
- 处理一组选择键上的任何就绪I/O
- 将NIO的缓冲区数据写入到通道中
- 关闭连接,比如network.Selector 对象,当前节点元数据对象,NIO的选择器等等。