Kafka生产者提交数据流程+源码解析

本文详细解析了Kafka生产者提交数据的完整流程,包括创建KafkaProducer、同步/异步发送数据、拦截器处理、序列化、分区策略、累积器以及数据发送到服务端等步骤。通过源码分析,加深了对Kafka生产者工作原理的理解。
摘要由CSDN通过智能技术生成

Kafka生产者提交数据流程

在平时的工作中,经常需要引入消息队列中间件,Kafka作为目前主流的消息队列,是程序员必不可少的技能。
本文结合kafka-clients源码回顾一下Kafka生产者提交数据的流程。kafka-clients版本为3.3.1,Java版本kafka-clients的maven路径:

<dependency>
   <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>3.3.1</version>
</dependency>

一、Kafka生产者提交数据整体流程

按照先整体再局部的方法,先复习一下Kafka生产者提交数据的整体流程,然后再从整体出发,剖析各个部分的细节。
Kafka提交流程

  1. Kafka发送之前需要创建KafkaProducer,调用send方法提交数据。
public class KafkaSendDemo {

    public static void main(String[] args) {
        Properties properties = new Properties();
        // 设置kafka集群地址
        properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"");
        // 设置key/value序列化方法
        properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        // 创建生产者
        KafkaProducer<String, String> producer = new KafkaProducer<>(properties);
        // 发送数据
        Future<RecordMetadata> send = producer.send(new ProducerRecord<>("topic1", 1, "hello", "hello"));

    }
}

Kafka支持同步提交和异步提交:同步提交调用send(ProducerRecord)方法; 异步提交调用send(ProducerRecord, Callback)方法。

  1. 调用send方法提交数据后,会接入拦截器,在拦截器中可以对数据进行过滤、转换等操作。通过实现 ProducerInterceptor<K, V>接口,并实现onSend方法可以自定义拦截器。随后在创建KafkaProducer时设置配置项interceptor.classes的值指定拦截器。
public class MyProducerInterceptor implements ProducerInterceptor<String, String> {
    @Override
    public ProducerRecord<String, String> onSend(ProducerRecord<String, String> record) {
        return null;
    }

    @Override
    public void onAcknowledgement(RecordMetadata metadata, Exception exception) {

    }

    @Override
    public void close() {

    }

    @Override
    public void configure(Map<String, ?> configs) {

    }
}
  1. 通过拦截器的数据会进入序列化器,在序列化器中对数据的key/value进行序列化操作。

  2. 序列化过后,Kafka会对数据进行分区,确定数据将写入topic中的哪个分区。确认分区的逻辑流程为:

    • 第一步,判断是否直接指定了分区,如果指定了分区直接退出;
    • 第二步,未指定分区的数据,判断是否指定了分区器,如果指定了分区器,则使用指定的分区策略设置分区。
    • 第三步,未指定分区且未设置分区器的数据,判断是否有key且key不应该被忽略,如果满足,则分区为:key哈希值对topic分区数量取模;否则返回-1,表示可以使用任意分区,后续使用内部逻辑确定分区(一般为随机分区)。
  3. 确认分区后,将数据放入累积器中,累积器的作用为:设置一个内存阈值和时间阈值,当数据累积到一定大小或到达时间节点,则向服务端传输数据,可以提高数据传输效率,内存阈值初始值为16KB。

  4. 通过Sender将满足条件的数据发送到服务端。

二、从源码中体现整个流程

1.发送数据,最终都是调用send(ProducerRecord<K, V> record, Callback callback)方法。
在这里插入图片描述
send(ProducerRecord<K, V> record, Callback callback)方法:
在这里插入图片描述

2.执行拦截器,在send(ProducerRecord<K, V> record, Callback callback)方法中,首先调用this.interceptors.onSend(record)方法,对已注册的拦截器进行一一调用。
interceptors类型为ProducerInterceptors<K, V>,改变量初始化逻辑为:如果在创建KafkaProducer是传入interceptors,则直接使用传入的interceptors;否则
从配置中获取 ProducerConfig.INTERCEPTOR_CLASSES_CONFIG配置值,创建interceptors。
在这里插入图片描述
this.interceptors.onSend(record)方法,遍历interceptors中的每个interceptor,每个interceptor执行onSend(record)方法,最后返回经过拦截器处理的数据。
在这里插入图片描述
3.序列化器
在执行序列化器之前,会先进行一些其他操作,如:

  • 将数据封装成AppendCallbacks对象,主要作用是当数据发送完成后调用拦截器的onAcknowledgement()方法;记录数据在topic中的分区号。
  • waitOnMetadata()方法检查更新topic信息,检查生产者是否关闭。

对key/value 进行序列化操作:
在这里插入图片描述
4.分区器
调用partition(ProducerRecord<K, V> record, byte[] serializedKey, byte[] serializedValue, Cluster cluster)计算数据的分区。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值