欢迎光临
我们一直在努力

kafka源码学习-生产者发送消息的后台调用逻辑

注:项目实际依赖版本(Spring Boot 2.7.18 → spring-kafka 2.8.11 → kafka-clients 3.1.x),从 kafkaTemplate.send("test_topic", content) 出发,梳理框架源码里的完整调用链。

一、从项目代码进入框架

调用:

kafkaTemplate.send("test_topic", content);

对应 KafkaTemplate<String, String> 的重载:

// spring-kafka 2.8.11 – KafkaTemplate.java

public ListenableFuture<SendResult<K, V>> send(String topic, @Nullable V data) {

ProducerRecord<K, V> producerRecord = new ProducerRecord<>(topic, data);

return doSend(producerRecord);

}

此时构造的 ProducerRecord 为:

  • topic = "test_topic"
  • key = null
  • value = content(你的 HTTP 参数 text)
  • partition = null(由分区器决定)
  • timestamp = null(由 Producer 填当前时间)

二、完整调用链总览

  • 三、分层详解

    第 1 层:Bean 从何而来(启动时)

    KafkaAutoConfiguration(Spring Boot 自动配置)在启动时创建:

    // KafkaAutoConfiguration.java

    @Bean

    public DefaultKafkaProducerFactory kafkaProducerFactory(…) {

    return new DefaultKafkaProducerFactory<>(this.properties.buildProducerProperties());

    // 读取 application.yml 中的 bootstrap-servers、acks、serializer 等

    }

    @Bean

    public KafkaTemplate kafkaTemplate(ProducerFactory kafkaProducerFactory, …) {

    return new KafkaTemplate<>(kafkaProducerFactory);

    }

    你的 application.yml 在这里被 KafkaProperties.buildProducerProperties() 转成 Map<String, Object>,最终传给 new KafkaProducer<>(configs, …)。


    第 2 层:KafkaTemplate.doSend() — Spring Kafka 核心

    protected ListenableFuture<SendResult<K, V>> doSend(final ProducerRecord<K, V> producerRecord) {

    // ① 获取 Producer 实例

    final Producer<K, V> producer = getTheProducer(producerRecord.topic());

    // ② 创建 Spring 侧的 Future(对 jdk Future 的包装)

    final SettableListenableFuture<SendResult<K, V>> future = new SettableListenableFuture<>();

    // ③ 调用原生 KafkaProducer,并注册回调

    Future<RecordMetadata> sendFuture =

    producer.send(producerRecord, buildCallback(producerRecord, producer, future, sample));

    // ④ 若同步失败(如序列化异常),立刻抛 KafkaException

    if (sendFuture.isDone()) {

    sendFuture.get(); // 可能抛异常

    }

    // ⑤ 若 autoFlush=true,立即 flush(默认 false)

    if (this.autoFlush) {

    flush();

    }

    return future; // 异步返回,不阻塞等待 Broker ack

    }

    要点:

  • doSend 本身是非阻塞的:立刻返回 ListenableFuture
  • 真正的 Broker 确认在 buildCallback 里异步完成
  • 你项目里没 .get(),所以 Controller 不会等 ack
  • send() 直接委托给 delegate.send()
  • close() 采用「借用/归还」语义:单次 send 结束后的 close() 通常不会真正销毁底层 Producer,而是留给下次复用
  • spring-kafka 2.8.11 KafkaTemplate
  • kafka-clients 3.1.2 KafkaProducer
  • kafka-clients 3.1.2 Sender
赞(0)
未经允许不得转载:171主机测评 » kafka源码学习-生产者发送消息的后台调用逻辑
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址