Kafka 精进:一文读懂 Producer 消息发送机制

栏目: IT技术 · 发布时间: 4年前

前面我们总结了broker端的核心参数,一些服务端原理细节后面文章再聊。本文我们重点讨论Producer端的消息发送机制,希望通过本文我们能 整体掌握 Producer端的原理。

1、Producer架构

一图胜千言,这里笔者画了一张Producer端消息发送的基本流程,如下图:

Kafka 精进:一文读懂 Producer 消息发送机制

总的来说,Kafka生产端发送数据过程涉及到序列化器Serializer、分区器Partitioner,消息缓存池Accumulator,还可能会涉及到 拦截器 Interceptor(这部分暂不做介绍) 。由于篇幅有限这里尽量做到言简意赅

2、客户端与数据结构

2.1 新旧Producer

Kafka 0.8.2引 入了新版本Producer客户端,并自0.9.0版本开始稳定并建议生产使用,新版本Producer是o.a.k.clients.producer.KafkaProducer,见:

//新版本Producer

org.apache.kafka.clients.producer.KafkaProducer<K,V>

//旧版本Producer

kafka.javaapi.producer.Producer<K,V>

与旧 版本相比,新版本Producer有点不同,一是连接Kafka方式上,旧版本连接的是Zookeeper,而新版本Producer连接的 是Broker;二是新版本Producer采用异步方式发送消息,与之前同步发送消息相对性能上大幅提升

2.2 消息数据结构

Kafka将一条待发送的消息抽象为ProducerRecord对象,其数据结构是:

public class ProducerRecord<K, V> {

private final String topic; //目标topic

private final Integer partition; //目标partition

private final Headers headers;//消息头信息

private final K key; //消息key

private final V value; //消息体

private final Long timestamp; //消息时间戳

//省略构造方法与成员方法

}

目前消息结构包括6个核心属性,分别是topic,partition,headers,key,value与timestamp,各属性含义如上也比较好理解,其中headers属性是Kafka 0.11.x 版本引入的,可以用它存储一些应用或业务相关的信息。

3、序列化机制

3.1 序列化与反序列化

Kafka遵守生产者消费者模式,这中间涉及到序列化与反序列化。Producer发送消息要通过序列化器(Serializer)将消息对象转换成字节数组,才能通过网络传输到服务端,消费端则需要通过反序列化器(Deserializer)从服务端拉取字节数组转成消息对象。可以用下图表示:

Kafka 精进:一文读懂 Producer 消息发送机制

生产端使用序列化器的方式非常简单,只要指定key.serializer与value.serializer即可,如下示例:

props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");

props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");

消费端使用的反序列化器要和生产端的序列化器要一一对应,否则将无法解析出想要的数据。

3.2 默认序列化器

目前Kafka提供了十几张序列化器,常见的序列化器有:

ByteArraySerializer // 序列化Byte数组,本质上什么都不用做。

ByteBufferSerializer // 序列化ByteBuffer。

BytesSerializer // 序列化Kafka自定义的Bytes类。

StringSerializer // 序列化String类型。

LongSerializer // 序列化Long类型。

IntegerSerializer // 序列化Integer类型。

ShortSerializer // 序列化Short类型。

DoubleSerializer // 序列化Double类型。

FloatSerializer // 序列化Float类型。

除了使用Kafka自带的序列化器,我们也可以自定义序列化器,只要实现Kafka Serializer接口并实现序列化逻辑即可,不过一般自带序列化器已经够用了。

4、消息分区机制

4.1 Topic分区

首先简单说一下分区的概念,可以用下图表示:

Kafka 精进:一文读懂 Producer 消息发送机制

分区即partition是Kafka中非常重要的概念,分区的作用主要是为Kafka提供负载均衡的能力,同时也是Kafka高吞吐量的保证。生产端要将数据发送到具体topic的某一个分区中,并且消息只在分区内有序。

4.2 分区器

消息通过send方法发送过程中,可能会经过分区器(Partitioner)的作用才能发往broker端。如果消息ProducerRecord中指定了partition字段,那么就不需要分区器的作用,因为partition代表的就是所要发往的分区号。

Kafka提供了默认分区器o.a.k.clients.producer.internals.DefaultPartitioner,并通过其partition()定义主要的分区分配逻辑。 接下来 我们看一下Kafka相关的分区策略。

4.3 分区策略

所谓分区策略就是决定消息发往具体分区所 采用的算法或逻辑 。目前Kafka主要 提供两种分区策略:哈希策略与轮询策略。

当没有为消息指定key即key为null 时,消息会以轮询的方式发送到各个分区(各个版本实现可能不一样,还有一种随机策略,有待考证);当key不为null时,默认分区器会使用 key的哈希值(采用Murmur2Hash算法)对partition数量取模,决定要把消息发送到哪个partition上。

5、消息缓冲池

5.1 缓存池介绍

生产端ProducerRecord经过序列化器、分区器处理后,并不是直接发往broker端,而是发送到客户端的消息缓冲池(Accumulator 中,最后交由Sender线程发往broker端。

缓冲池最大大小由参数buffer.memory控制,默认是32M,当生产消息的速度过快导致buffer满了的时候,将阻塞max.block.ms时间,超时抛异常,所以buffer的大小可以根据实际的业务情况进行适当调整。

5.2 批量发送

发送到缓冲池中消息将会被分为一个一个的batch,分批次的发送到broker 端,批次大 小由参数batch.size控制,默认16KB。 这就意味着正常情况下消息会攒够16KB时才会批量发送到broker端,所以一般减小batch大小有利于降低消息延时,增加batch大小有利于提升吞吐量。

但是消息并不是必须要达到一个batch尺寸才会批量发送到服务端呢,Producer端提供了另一个重要参数linger.ms,用来控制batch最大的空闲时间,超过该时间的batch也会被发送到broker端。

6、总结

本文先是介绍了Producer客户端与ProducerRecord数据结构,然后重点介绍了序列化器Serializer、分区器Partitioner以及消息缓冲池Accumulator的基本原理,由于篇幅有限,还有一些细节比如拦截器、Sender线程并未涉及到,后续我们再来讨论 。希望通过本文读者可以对Producer端消息发送机制有一个比较整体的认识。

Kafka 精进:一文读懂 Producer 消息发送机制


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

浪潮之巅(上册)

浪潮之巅(上册)

吴军 / 人民邮电出版社 / 2013-5-1 / 35.00元

《浪潮之巅(第2版)(上册)》不是一本科技产业发展历史集,而是在这个数字时代,一本IT人非读不可,而非IT人也应该阅读的作品。一个企业的发展与崛起,绝非只是空有领导强人即可达成。任何的决策、同期的商业环境,都在都影响着企业的兴衰。《浪潮之巅》不只是一本历史书,除了讲述科技顶尖企业的发展规律,对于华尔街如何左右科技公司,以及金融风暴对科技产业的冲击,也多有着墨。此外,《浪潮之巅》也着力讲述很多尚在普......一起来看看 《浪潮之巅(上册)》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具