1. 生产者原理图
2. 概述
- Producer客户端是由两个线程协调运行,
主线程
和Sender线程
- 主线程负责将消息发送到消息累加器[
RecordAccumulator
]中 RecordAccumulator
缓存消息,以便消息可批量发送Sender线程
负责从RecordAccumulator
中获取消息,并将消息发送到Kafka
集群.
3. 原理解析
3.1 主线程
在主线程中,Producer
生成消息后,经过拦截器[ProducerInterceptor
]、序列化器[Serializer
]、分区器[Partitioner
]后将数据发送给RecordAccumulator
-
Producer
负责生成消息
-
ProducerInterceptor
在
Producer
生成消息后,可以通过ProducerInterceptor
对消息进行统一处理,不过一般很少用到到,因为我们可以在生成消息时就处理好,如果是涉及到了客户端监控、端到端系统性能检测、系统审计等功能在内的场景可以利用到拦截器 -
Serializer
根据指定的序列化器将对象转化成字节数组存储到
Kafka
中注意:生产者和消费者的序列化器必须是一一对应的关系,因为消费者是利用反序列化器将字节数组转换成对象.
-
Partitioner
对
key
进行哈希,根据哈希值计算分区,相同key
的消息会被发送到相同的分区,默认的分区器是org che.kafka.clients.producer intemals.DefaultPartitioner
.
3.2 RecordAccumulator
RecordAccumulator
主要用以缓存消息,以批量的形式发送,可以有效减少网络IO的资源消耗以提升性能.
参数 | 值 | 作用 |
---|---|---|
buffer.memory | 默认33554432B | 配置RecordAccumulator的缓存大小 |
max.block.ms | 默认60000(60秒) | 当生产者发送消息的速度超过send将消息发送到服务器的速度时,会导致生产者空间不足,这时KafkaProducer.send 方法会阻塞,当阻塞时间达到默认的60秒时会抛出异常. |
-
Deque
双端队列,在
RecordAccumulator
内部,为每个Partition
维护了一个双端队列Deque<ProducerBatch>
,消息写入时,追加到双端队列的尾部,读取消息时从头部开始读取. -
ProducerBatch
ProducerBatch
是指一个消息的批次,Send
从双端队列的尾部读取消息时,会将小的ProducerBatch
合并成一个大的ProducerBatch
,这样也会减少网络请求的次数以提升整体的吞吐量.当有消息[
ProducereRedcord
]流入到RecordAccumulator
中时,会寻找该ProducerRecord
对应分区的双端队列[Deque
](如果Deque
不存在则新建),然后从Deque
尾部获取一个ProducerBatch
(如果ProducerBatch
没有则新建),判断该ProducerBatch
是否还可以写入ProducerRecord
,如果不可以则新建一个ProducerBatch
参数 值 作用 batch.size 默认值16KB 用来设置batch.size的大小.当一个 ProducerBatch
的中的消息存满后,会根据新的ProducerRecord
的大小进行判断,如果小于设置的batch.size的大小则根据batch.size新建一个ProducerBatch
3.3 Sender
Sender
从RecordAccumulator
拉取到数据后,在将数据发送给Kafka
集群,消息在RecordAccumulator
中存储形式为<Partation,Deque<ProducerBatch>>
,Sender
将数据拉取过来后,数据形式变为<Node,List<ProducerBatch>>
,Node
代表Kafka
集群的broker
节点,而后Sender
在将<Node,List<ProducerBatch>>
进一步封装成<Node,Request>
-
InFlightRequests
Sender
线程在将请求发送到Kafka
前会保存到InFlightRequests
,数据保存形式为Map<NodeId,Deque<Request>>
,NodeId
代表broker
的id
编号.参数 值 作用 max.in.flight.request.per.connection 默认值5 管理客户端与 Node
之间的连接最多能缓存的未响应的请求数,超过该数值后,则不能向这个连接发送更多的请求max.request.size 默认1048576B 限制生产者发送消息的最大值 -
Request
Request
是Kafka
的各种协议请求,用以缓存已经发出但是还没有收到服务器端响应的请求. -
Request
Request
是Kafka
的各种协议请求,用以缓存已经发出但是还没有收到服务器端响应的请求.可以通过
<Deque<Reqquest>>
的size
与max.in.flight.request.per.connection
参数的大小比较来判断对应的Node
中是否已经堆积了很多未响应的消息,这样可以帮助我们判断Node
是否存在负载过重或者网络连接存在问题.