了解Kafka生产者
了解Kafka生产者
之前对kafka的整体架构有浅显的了解,这次正好有时间,准备深入了解一下kafka,首先先从数据的生产者开始吧。
生产者的整体架构

可以看到整个生产者进程主要由两个线程进行协调工作,其中一个是主线程,首先由KafkaProducer创建消息,然后通过拦截器、消息序列化器、分区器的处理后,缓存到消息累加器中。另一个是Sender线程,负责从消息累加器中获取消息,并发送至Kafka集群中。
下面来具体分析各个组件的作用,以便加深了解。
拦截器: 从名字就可看出是按照一定规则对消息进行过滤。这个具体的规则可以自己去重写kafka中的ProducerInterceptorPrefix类中的onSend方法来实现。之后在KafkaProducer的配置参数 interceptor.classes中指定该拦截器来进行使用。还可以指定多个拦截器,组成拦截链。
序列化器:生产者需要使用它将消息对象转化为字节数组发送给kafka集群。消费者端进行反序列化还原消息对象。kafka中自带序列化器StringSerializer可对String、VyteArray、ByteBuffer等等类型进行序列化。kafka支持自定义序列化器,实现Serializer,重写serialize方法,即可实现自定义序列化器。修改配置文件中的value.serializer参数为自定义的类名即可。
分区器:顾名思义,分区器就是控制消息最终发往那个分区。若ProducerRecord中指定了partition字段,将发往指定的分区。反之,将根据消息的key来计算partition的值,拥有相同key的消息会被写入同一分区,key为null的消息,将会以轮询的方式发往topic内的各个可用分区。topic中的分区数量不变时,key与分区之间的映射关系保持不变。当topic内的分区数量变化时,该关系将难以保持。
注意:
如果key为null,计算得到的分区号仅为可用分区中的任意一个。当key不为null时,计算得到的分区号是所有分区中的任意一个。
当然,分区器也可以自定义,实现Partitioner中的partition方法即可。同样也是通过配置参数partitioner.class来显式指定这个分区器。
消息累加器:RecordAccumulator主要用来缓存消息,使Sender线程可以批量发送消息,进而减少网络传输的前期准备和收尾的资源消耗,提升性能和效率。缓存大小可以通过buffer.memory配置,默认值32MB。主程序生产的消息(ProducerRecord)都会追加到ProducerBatch尾部。消息累加器里面维护了一个Deque,他们之间的关系是多个ProducerRecord组成了一个ProducerBatch,多个ProducerBatch组成了一个Deque,这样的结构同样也是为了使消息排列更紧凑,提升效率和性能。
消息在生产端的生命历程
在RecordAccumulator内部还有一个BufferPool,用来实现ByteBuffer的复用,以实现缓存的高效利用,不过BufferPool只针对特定大小的ByteBuffer,其他大小的ByteBuffer不会缓存进BufferPool,这个特定大小由batch.size来指定,默认值为16KB。
当消息进入RecordAccumulator时,会先寻找指定分区所对应的Deque(若无将创建),再从Deque获取尾部的PoducerBatch(若无将创建),查看是否还能写入该消息(ProducerRecord),若可以则写入,否则将创建一个新的ProducerRecord,在创建时评估消息大小是否超过batch.size的大小,若不超过,PoducerBatch大小为该值,超过的话,将以消息大小创建PoducerBatch。换句话说,该PoducerBatch中仅有一条消息。
以batch.size创建的PoducerBatch可以通过BufferPool的管理来进行复用。
Sender从RecordAccumulator中获取缓存的消息之后,会将消息格式<分区,Deque>转换为<Node,List>,Node为kafka集群中的broker节点。之后Sender还会进一步封装成<Node,Request>的形式,这样就可以将Request请求发往各个Node了。请求在从Sender线程发往Kafka之前还会保存到InFlightRequests中,消息格式为Map<NodeId,Deque>,主要作用是缓存了已经发出去但还没有收到响应的请求。InFlightRequests可以通过配置参数来限制每个连接最多缓存的请求数。配置参数为max.in.flight.requests.per.connection,默认值为5。类似于golang中的channel,通道中的未响应请求数量达到5个,将阻塞,当被缓存的未响应请求收到响应,可以继续添加。
生产端的元数据更新
kafka中的元数据:集群中的topic信息,每个topic有哪些分区,每个分区的leader副本分配在哪个节点上,follower副本分配在哪些节点上,具体哪些副本在AR、ISR等集合中,集群中有哪些节点,控制器节点是哪个等信息。
当生产者客户端发送的消息中缺失需要的元数据时(例如未指定topic),或超过metadata.max.age.ms 时间没有更新元数据都会引起元数据的更新操作。默认值为5分钟。元数据的更新是在客户端内部进行的,对外部使用者不可见,也就是开发者不可感知到元数据的更新。当需要更新元数据时,会先挑选出lwastLoaderNode,然后向这个Node发送MetadataRequest请求来获取具体的元数据信息,该操作由Sender发起,在创建完MetadayaRequest之后,会存入InflightRequests,之后的步骤和发送消息类似,元数据的更新虽然由Sender线程负责更新,但是主线程也需要读取这些信息,这里的数据同步通过synchronized和final关键字来保障。
今天也是了解了大概的原理,每个细节都值得去深挖,故写文自勉。
了解Kafka生产者的更多相关文章
- 【转】 详解Kafka生产者Producer配置
粘贴一下这个配置,与我自己的程序做对比,看看能不能完善我的异步带代码: ----------------------------------------- 详解Kafka生产者Produce ...
- Kafka生产者-向Kafka中写入数据
(1)生产者概览 (1)不同的应用场景对消息有不同的需求,即是否允许消息丢失.重复.延迟以及吞吐量的要求.不同场景对Kafka生产者的API使用和配置会有直接的影响. 例子1:信用卡事务处理系统,不允 ...
- Python 使用python-kafka类库开发kafka生产者&消费者&客户端
使用python-kafka类库开发kafka生产者&消费者&客户端 By: 授客 QQ:1033553122 1.测试环境 python 3.4 zookeeper- ...
- Kafka集群安装部署、Kafka生产者、Kafka消费者
Storm上游数据源之Kakfa 目标: 理解Storm消费的数据来源.理解JMS规范.理解Kafka核心组件.掌握Kakfa生产者API.掌握Kafka消费者API.对流式计算的生态环境有深入的了解 ...
- [Spark][kafka]kafka 生产者,消费者 互动例子
[Spark][kafka]kafka 生产者,消费者 互动例子 # pwd/usr/local/kafka_2.11-0.10.0.1/bin 创建topic:# ./kafka-topics.sh ...
- Kafka权威指南 读书笔记之(三)Kafka 生产者一一向 Kafka 写入数据
不管是把 Kafka 作为消息队列.消息总线还是数据存储平台来使用 ,总是需要有一个可以往 Kafka 写入数据的生产者和一个从 Kafka 读取数据的消费者,或者一个兼具两种角色的应用程序. 开发者 ...
- kafka生产者
1.kafka生产者是线程安全的,她允许多个线程共享一个kafka实例 2.kafka管理一个简单的后台线程,所有的IO操作以及与每个broker的tcp连接通信,如果没有正确的关闭生产者可能会造成资 ...
- java实现Kafka生产者示例
使用java实现Kafka的生产者 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 3 ...
- kafka生产者和消费者流程
前言 根据源码分析kafka java客户端的生产者和消费者的流程. 基于zookeeper的旧消费者 kafka消费者从消费数据到关闭经历的流程. 由于3个核心线程 基于zookeeper的连接器监 ...
- JAVA封装消息中间件调用一(kafka生产者篇)
这段时间因为工作关系一直在忙于消息中间件的发开,现在趁着项目收尾阶段分享下对kafka的一些使用心得. kafka的原理我这里就不做介绍了,可参考http://orchome.com/kafka/in ...
随机推荐
- MBE风格图标
图标的定义 图标是一种通过相似性或类比行来代表对象的符号. 图标的重要性 1.图形以其无与伦比的识别性带来信息传达效率的提升. 2.图形以其百变多样的趣味性带来视觉体验的享受提成用户体验. 3.图形以 ...
- P 1017
转跳点:
- 每天一点点之vue框架开发 - vue坑-input 的checked渲染问题
选中radio或者checkbox需要注意的是: 不管<input type='radio checked='true''> 你的checked属性值是true或者false,他都会选中 ...
- 如何拖拽DIV边线并左右自适应改变大小?
//树图拉伸 jQuery(function ($){ var doc = $(document), dl = $(".side-tree" ...
- UVA 10054 The Necklace 转化成欧拉回路
题意比较简单,给你n个项链碎片,每个碎片的两半各有一种颜色,最后要把这n个碎片串成一个项链,要求就是相邻碎片必须是同种颜色挨着. 看了下碎片总共有1000个,颜色有50种,瞬间觉得普通方法是无法在可控 ...
- python刷LeetCode:13. 罗马数字转整数
难度等级:简单 题目描述: 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值I 1V 5X 10L 50C 100D 500M 1000例如, 罗马数字 2 写做 II ...
- 高级css效果
1.图片渐变效果 background linear-gradient(top,rgba(0,0,0,.8),rgba(0,0,0,.8))
- Spring中的控制反转和依赖注入
Spring中的控制反转和依赖注入 原文链接:https://www.cnblogs.com/xxzhuang/p/5948902.html 我们回顾一下计算机的发展史,从最初第一台计算机的占地面积达 ...
- 201771010123汪慧和《面向对象程序设计JAVA》第六周实验总结
一.理论部分: 1.继承 用已有类来构建新类的一种机制.当定义了一个新类继承了一个类时,这个新类就继承了这个类的方法和域,同时在新类中添加新的方法和域以适应新的情况. 2.类.超类.子类 (1)类继承 ...
- PAT 2011 秋
A : World Cup Betting #include <cstdio> #include <iostream> #include <algorithm> u ...