写点什么

Kafka- 探险 --- 生产者源码分析 --- 核心组件,2021 年 Java 社招面试题精选

用户头像
极客good
关注
发布于: 刚刚
  1. 消息异步写入缓冲区,网络 I/O 线程实现消息发送

  2. 消息发送的失败重试机制


话不多说,用一张图画出各个核心模块以及他们之间的交互顺序:



用户设定 Kafka 集群信息,生产者从 Kafka Broker 上拉取 可用 Kafka 节点、Topic 以及 Partition 对应关系。缓存到生产者成员变量中,如果 Broker 集群有扩容,或者有机器下线需要重新获取这些服务信息。


客户端根据用户设置的序列化器,对消息进行序列化,之后异步的将消息写入到客户端缓冲区。缓冲区内的消息到达一定的数量或者到达一个时间窗口后,网络 I/O 线程将消息从缓冲区取走,发送到 Broker 。


以上就是我对于一个 Kafka 生产者实现的思考,接下来看看官方的代码设计与我们的思路有何差别,他又是为什么这么设计。

官方设计

其实经过上面的思考和整理,我们的设计已经非常接近 Kafka 的官方设计了,官方的模块拆分的更加细致,功能更加独立。

核心组件

首先看一眼 KafkaProducer 类中有哪些成员变量,这些变量就是 Producer 的核心组件。



其中核心字段的解释如下:


clinetId :标识发送者 Id


metric :统计指标


partitioner :分区器作用是决定消息发到哪个分区。有 key 则按照 key 的 hash ,否则使用 roundrobin


key/value Serializer :消息 key/value 序列化器


interceptors :发送之前/后对消息的统一处理


maxRequestSize :可以发送的最大消息,默认值是 1M,即影响


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


一个消息 Record 的大小,此值在服务端也是有限制的。


maxBlockTimeMs :buffer 满了或者等待 metadata 信息的,超时的补偿机制


accumulator :累积缓冲器


networkClient :包装的网络层


sender :网络 I/O 线程

发送流程

发送一条消息的时候,数据又是怎样在这些组件之间进行流转的呢?



Producer 调用 send 方法后,在从 Broker 获取的 Metadata 有效情况下,经过拦截器和序列化后,被分区器放到了一个缓冲区的特定位置,缓冲区由一个 ConcurrentHashMap 构成,key 为主题分区,value 是一个 deque 存放消息缓存块。从客户端角度来看如果无需关心发送结果,发送流程就已经结束了。


接下来是独立的 Sender 线程负责从缓冲中获取足量的数据调用 Network Client 封装层去真正发送数据,这里使用了 Java8 的 NIO 网络模型发送数据。


可以看到整个逻辑的关键点在于 RecordAccumulator 如何进行消息缓存,一般的成熟框架和中间件中都会有一套自己的内存管理机制,比如 Netty 也有一套复杂而又精妙的内存管理抽象层,这里的缓冲区也是一样的道理,主要需要去看看 Kafka 如何去做内存管理。


另外需要关注 Sender 从缓冲里以什么样的逻辑获取数据,来达到尽量少的网络交互发送尽量多的数据。还有网络失败又是如何保证数据的可靠性的。这个地方也是我们的设计和官方实现的差距,对于网络 I/O 的精心优化。

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Kafka-探险---生产者源码分析---核心组件,2021年Java社招面试题精选