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

}

要点: