这个时候,如果你去深究红黑树、为什么是 8 不是别的,又去查 泊松分布,最终会慢慢的搞死自己。
所以,正确的做法,我们先把这一部分给略过去,知道这个概念即可,等后面我们把整个庐山看完之后,再回过头抠细节。
当然,本章我们讲述 Kafka 生产者的网络架构
一、引言
kafka生产端的组成主要由以下几方面构成:
- 生产端的初始化
- 元数据的更新
- 缓存池(BufferPool)机制
- 网络架构模型
- 消息发送
其中,我们 生产端的初始化、元数据的更新、缓存池(BufferPool)机制已经介绍完毕,今天我们来看看 网络架构模型
废话不多说,老司机开始发车
二、网络架构模型
从我们之前的讲解中,我们可以知道,生产端最重要的几个技术点:
- KafkaProducer:主要将消息发送至
RecordAccumulator
并唤醒Sender
- Sender:调用
NetworkClient
将RecordAccumulator
的消息发送至Broker
- NetworkClient:
Kafka
对Java NIO
的封装
而正是它们几个组成了 Kafka 生产者的网络架构,其网络模型如下:
不难看出,我们 Kafka
生产者最终的网络架构也是使用的 Java NIO
,和我们的 Netty
殊途同归。
至于 kafka
为什么不用 Netty
做通信组件,这个之间在 【Kafka从成神到升仙系列 三】你真的了解 Kafka 的元数据嘛 已经讲过,此处不再叙述,有兴趣的同学可以跳转阅读。
三、网络架构整体流程
上面我们了解了 Kafka
生产端的几个网络组件及其对应的关系
我们深入的看一下,这几个组件之间到底是如何进行数据的处理及业务的处理的
网络架构整体流程如下所示:
这里涉及的主要几个方法:
- KafkaProducer
- waitOnMetadata:等待更新元数据
- accumulator.append:消息发送到缓冲区
- sender.wakeup:唤醒
Sender
线程
- Sender
- accumulator.ready:得到符合发送规定的节点
- metadata.requestUpdate:是否更新元数据
- remove any nodes:删除尚未建立连接的节点
- accumulator.drain:得到每个节点需要发送的消息批次
- createProduceRequests:组装成客户端请求
- client.send:调用
NetworkClient
设置事件类型 - client.poll:调用
NetworkClient
发送消息
- NetworkClient
- send:调用
Selector
设置事件类型 - poll:调用
Selector
发送消息
- send:调用
- Kafka-Selector
- send:设置事件类型
- poll:发送消息
可能大多数的小伙伴这个时候已经有点晕了,没关系,我们本篇文章就是解决你晕的问题的
我们会从 Producer
的源码一直会讲到 Selector
的源码并最终通过打日志的方式验证我们的猜想
戴好安全带,我们发车了
四、网络架构源码剖析
1、KafkaProducer
对于 KafkaProducer
来说,其最重要的功能就是将 record
发送至我们的 RecordAccumulator
中去
1.1 waitOnMetadata
这个方法相信看过上篇博客:【Kafka从成神到升仙系列 三】你真的了解 Kafka 的元数据嘛,已经有印象
对,没错,这个就是我们 kafka
在发送消息时,会优先请求 Broker
获取元数据信息,然后再去发送消息
具体细节的话,这里也不叙述了
总之:第一次发送消息时,这里会判断当前是否拿到了元数据。如果没有拿到元数据信息,这里会堵塞循环并唤醒 Sender
线程,让其帮忙更新元数据。
1.2 accumulator.append
这个其实我们这篇博客中也讲过:【Kafka从成神到升仙系列 二】生产者如何将消息放入到内存缓冲区
具体的细节如上,更多的细节可以参考上面那篇博客
1.3 sender.wakeup
当我们 **首次获取元数据 **或者 当前的 batch 满了 或者 一个新的 batch 创建了,我们都可以去唤醒我们的 Sender
,让这个线程执行我们的业务。
- 首次获取元数据:让
Sender
去更新元数据信息 - 当前的
batch
满了 或者 一个新的batch
创建:让