kafka生产者原理分析

生产者客户端整体架构:
在这里插入图片描述

​ 整个生产者客户端由两个线程协调运行,这两个线程分别为主线程和Sender线程(发送线程)。在主线程中由KafkaProducer创建消息,然后通过可能的拦截器、序列化器和分区器的作用之后缓存到消息累加器(RecordAccumulator,也称为消息收集器)中。Sender线程负责从RecordAccumulator中获取消息并将其发送到kafka中。

​ RecordAccumulator主要用来缓存消息以便Sender线程可以批量发送,进而减少网络传输的资源消耗以提升性能。RecordAccumulator缓存的大小可以通过生产者客户端参数buffer.memory配置,默认值为33554432B,即32M。如果生产者发送消息的速度超过发送到服务器的速度,则会导致生产者空间不足。这个时候KafkaProducer的send()方法调用要么被阻塞,要么抛出异常,这个取决于参数max.block.ms的配置,此参数的默认值为60000,即60s。

​ 主线程发送过来的消息都会被追加到RecordAccumulator的某个双端队列Deque中,在RecordAccumulator的内部为每个分区都维护了一个双端队列,队列中的内容就是ProducerBatch,即Deque。消息写入缓存时追加到双端队列的尾部;Sender读取消息时,从双端队列的头部读取。ProducerBatch中可以包含一个至多个ProducerRecord,这样可以使字节更加紧凑并且可以减少网络请求的次数以提升整体的吞吐量。如果生产者客户端需要向很多分区发送消息,则可以将buffer.memory参数适当调大以提升整体的吞吐量。

​ 消息在网络上都是以字节(Byte)的形式存储的,在发送之前需要创建一块内存区域来保存对应的消息。在kafka生产者客户端中,通过java.io.ByteBuffer实现消息内存的创建和释放。不过频繁的创建和释放是比较耗费资源的,在RecordAccumulator的内部还有一个BufferPool,它主要用来实现ByteBuffer的复用,以实现缓存的高效利用。不过BufferPool只针对特定大小的ByteBuffer进行管理,这个大小由batch.size参数来指定,默认值为16384B,即16KB。我们可以适当地调大参数以便可以缓存更多消息。

​ ProducerBatch的大小和batch.size参数也有密切的关系。当一条消息(ProducerRecord)流入RecordAccumulator时,会先寻找与消息分区所对应的双端队列(如果没有则新建),再从这个双端队列的尾部获取一个ProducerBatch(如果没有则新建),查看ProducerBatch是否还可以写入这个ProducerRecord,如果可以则写入,如果不可以则需要创建一个新的ProducerBatch。在创建ProducerBatch时评估这条消息的大小是否超过batch.size,如果不超过,那么就以batch.size的参数大小来创建ProducerBatch,这样在使用完这块内存区域后,可以通过BufferPool的管理来进行复用;如果超过,那么就以评估的大小来创建ProducerBatch,这段内存区域不会被复用。


实时内容请关注微信公众号,公众号与博客同时更新:程序员星星
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章