源码分析 Kafka 消息发送流程(文末附流程图)

本文详细解释了Kafka消息发送的过程,涉及ProducerRecord的构建,包括序列化key和value、分区策略的选择、以及消息追加至缓存区和异步发送的机制。特别关注RecordAccumulator的append方法及其内部逻辑。
摘要由CSDN通过智能技术生成
  • String topic

消息所属的主题。

  • Integer partition

消息所在主题的队列数,可以人为指定,如果指定了 key 的话,会使用 key 的 hashCode 与队列总数进行取模来选择分区,如果前面两者都未指定,则会轮询主题下的所有分区。

  • Headers headers

该消息的额外属性对,与消息体分开存储.

  • K key

消息键,如果指定该值,则会使用该值的 hashcode 与 队列数进行取模来选择分区。

  • V value

消息体。

  • Long timestamp

消息时间戳,根据 topic 的配置信息 message.timestamp.type 的值来赋予不同的值。

  • CreateTime

发送客户端发送消息时的时间戳。

  • LogAppendTime

消息在 broker 追加时的时间戳。

其中Headers是一系列的 key-value 键值对。

在了解 ProducerRecord 后我们开始来探讨 Kafka 的消息发送流程。

2、Kafka 消息追加流程


KafkaProducer 的 send 方法,并不会直接向 broker 发送消息,kafka 将消息发送异步化,即分解成两个步骤,send 方法的职责是将消息追加到内存中(分区的缓存队列中),然后会由专门的 Send 线程异步将缓存中的消息批量发送到 Kafka Broker 中。

消息追加入口为 KafkaProducer#send

public Future send(ProducerRecord<K, V> record, Callback callback) {

// intercept the record, which can be potentially modified; this method does not throw exceptions

ProducerRecord<K, V> interceptedRecord = this.interceptors.onSend(record); // @1

return doSend(interceptedRecord, callback); // @2

}

代码@1:首先执行消息发送拦截器,拦截器通过 interceptor.classes 指定,类型为 List< String >,每一个元素为拦截器的全类路径限定名。

代码@2:执行 doSend 方法,后续我们需要留意一下 Callback 的调用时机。

接下来我们来看 doSend 方法。

2.1 doSend

KafkaProducer#doSend

ClusterAndWaitTime clusterAndWaitTime;

try {

clusterAndWaitTime = waitOnMetadata(record.topic(), record.partition(), maxBlockTimeMs);

} catch (KafkaException e) {

if (metadata.isClosed())

throw new KafkaException(“Producer closed while send in progress”, e);

throw e;

}

long remainingWaitMs = Math.max(0, maxBlockTimeMs - clusterAndWaitTime.waitedOnMetadataMs);

Step1:获取 topic 的分区列表,如果本地没有该topic的分区信息,则需要向远端 broker 获取,该方法会返回拉取元数据所耗费的时间。在消息发送时的最大等待时间时会扣除该部分损耗的时间。

温馨提示࿱

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值