图解 Kafka 生产者初始化核心流程

网站建设4年前发布
38 0 0

从今天开始我将以「 Kafka 2.7」 版本为主,通过「场景驱动」的方式带大家一点点的对 Kafka 源码进行深度剖析,正式开启 Kafka的源码之旅」,跟我一起来掌握 Kafka 源码核心架构设计思想吧。,今天这篇我们先来聊聊 Kafka 生产者初始化时用到的核心组件以及发送的核心流程,带你梳理生产者初始化整体的源码分析脉络。,认真读完这篇文章,我相信你会对 Kafka 生产初始化源码有更加深刻的理解。,这篇文章干货很多,希望你可以耐心读完。,我们都知道在 Kafka 中,我们把产生消息的一方称为生产者即 Producer,它是 Kafka 核心组件之一,也是消息的来源所在。那么这些生产者产生的消息是如何传到 Kafka 服务端的呢?初始化过程是怎么样的呢?接下来会逐一讲解说明。,我们先从生产者客户端构造 KafkaProducer开始讲起:,上面代码主要做了2件事情:,待构造完 KafkaProducer 就正式进入生产者源码的入口了,如下图所示:,接下来我们分析一下 KafkaProducer 的源码, 先看下该类里面的重要字段:,重要且核心字段含义如下:,接下来我们看下 KafkaProducer 的构造方法,来剖析生产者发送消息的过程中涉及到的「核心组件」。,源码位置:,如果有不会安装源码环境的话,可以参考之前的 Kafka源码之旅入门篇。,下面通过一张图来描述 KafkaProducer 的初始化源码过程:,Kafka Producer 初始化核心组件如下:,我们分析了 KafkaProducer 的核心组件,接下来我们分析下初始化过程中的核心流程。,初始化消息累加器对象「accumulator」,部分重要参数如下:,消息累加器---缓冲区的设计是 Kafka Producer 非常优秀和经典的设计,Kafka 中消息不是生产后立马就发送给服务端的,而是会先写入一个缓冲池中,然后直到多条消息组成了一个 Batch,达到一定条件才会一次网络通信把 Batch 发送过去,利用该设计来避免 JVM 频繁的 Full GC 的问题,后续会单独对其进行深度剖析。,元数据的获取涉及的组件比较多,主要分为:,首先我们来看下 KafkaProducer 主线程是如何加载元数据。,元数据「metadata」的初始化的时候是在 KafkaProducer 主线程里面的,源代码如下:,它会保存在客户端内存中,并与服务端保持准实时的数据一致性,元数据主要包含:,从上面源代码我们可以看出在 KafkaProducer 的构造方法中初始化了元数据类「metadata」,然后调用 「metadata.bootstrap()」来启动引导程序,这个时候 metaData 对象里并没有具体的元数据信息,因为客户端还没发送元数据更新的请求「获取是通过唤醒 Sender 线程进行发送的」。,而具体的发送和拉取,我们将在下一篇中进行剖析。,这里非常关键,初始化 「Sender」发送线程类,并同时初始化 「NetworkClient」,它为 sender 提供了网络IO的能力,后续我们会对其深度剖析。,从上面源代码可以看出使用「ioThread」线程来封装 「Sender」 线程类,并使用 demon 守护线程方式来启动 Sender 线程类。,这里的设计模式非常值得我们去学习,就是在设计一些后台线程的时候,可以把「线程本身」和「线程执行」的逻辑分开,Sender 线程就是线程执行的具体逻辑,而 KafkaThread 其实代表了这个「线程本身」、「线程的名字」、「未捕获的异常处理」,「deamon 线程设置」。对 KafkaThread 的启动会自动执行 Sender 线程的 Run() 方法。,用户可以直接使用 「producer.send()」 进行数据的发送,先看一下 Send()接口的源码实现。,生产环境我们一般会使用带回调函数的方式去发送,所以最终实现还是调用了 KafkaProducer 的 doSend() 接口。,该方法只是把消息发送到缓冲区后直接返回,真正的发送是需要等待 Sender 线程把消息从缓冲区将消息取出来后再进行发送。,源码比较长,这里只简单的分析下都做了哪些事情,后续再进行深度剖析,源码如下:,这里,我们一起来总结一下这篇文章的重点。,1、通过「场景驱动」的方式从生产者调用出发,抛出初始化和发送的过程是怎样的?,2、带你梳理了「Kafka Producer 初始化源码全貌」,包含主线程的核心组件模块以及消息累加器的初始化、元数据初始化、 Sender 线程初始化流程。,3、最后通过一张整体发送流程图来勾勒出生产者发送消息的全貌。

© 版权声明

相关文章