Kafka发送消息整体归纳
- 入口KafkaProducer#doSend将消息按主题分区维护追加缓存区
- Sender线程从缓存区中取出符合要求的消息发送Broker中
KafkaProducer#doSend分析
总结KafkaProducer#doSend方法
- 获取topic的分区列表
- 序列化key
- 对消息内容进行序列化
- 根据分区负载算法计算本次消息发送该发往的分区
- 如果是消息头信息(RecordHeaders),则设置为只读
- 根据使用的版本号,按照消息协议来计算消息的长度
—> 超过指定长度则抛出异常 - 先初始化消息时间戳,并对传入的 Callable(回调函数) 加入到拦截器链中
- 将消息追加到缓存区(重点)
- 针对各种异常,进行相关信息的收集
将消息追加到缓存区 RecordAccumulator#append
纵观 RecordAccumulator append 的流程,基本上就是从双端队列获取一个未填充完毕的 ProducerBatch(消息批次),然后尝试将其写入到该批次中(缓存、内存中),如果追加失败,则尝试创建一个新的 ProducerBatch 然后继续追加
将记录追加到当前记录集ProducerBatch#tryAppend
Sender#sendProducerData分析
总结Sender#sendProducerData方法
- 据上图所示,从缓存区RecordAccumulator中挑选已达到条件的数据,最终会封装成InFlightRequest对象,放在inFlightRequests集合
- selector.send(send)
2.1 根据connectionId得到对应KafkaChannel
2.2 将send赋值给KafkaChannel的send属性以及在注册写事件(查看NetworkClient#poll分析)
NetworkClient#poll
- 当写事件就绪后,就会将通道中的消息发送到远端的broker
- 处理任何已完成的请求发送