作者:zykBlog

链接:https://www.cnblogs.com/zykBlog

来源:https://www.cnblogs.com/zykBlog

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Kafka Produer发送消息的基本原理

Kakfa Producer发送消息的流程

Kakfa生产者客户端的整体架构,如下图所示

主线程和Sender线程协调运行。在主线程中由KakfaProducer创建消息,然后经过拦截器、序列化器、分区器的左右之后,缓存消息累加器中。最后通过Sender线程负责将消息发送到Kafka中。

RecordAccumulator缓存消息

RecordAccumulator主要用来缓存消息,使得Sender线程可以批量发送消息,这样可以减少网络传输资源的消耗,提升性能。RecordAccumulator缓存的默认大小是32MB,可以通过buffer.memory进行配置。如果生产者发送消息的速度超过发送到Kakfa的速度,就会导致缓存的空间不足,此时send()方法被调用的时候就会被阻塞或者抛出异常,这个取决于参数max.block.ms,默认是60秒。

主线程发送的消息会被添加到RecordAccumulator的某个双端队列中,队列中的内容就是ProducerBatch。写入消息时,直接追加到双端队列的尾部。Sender读取消息时,从双端队列头部开始读取。在ProducerBatch中包含多个ProducerRecord,消息批量发送,可以减少网络请求的次数以提高系统整体的吞吐量。消费者客户端如果需要向很多分区发送消息,可以调整buffer.memory参数调整系统的吞吐量。

ProducerBatch的大小可以通过batch.size参数来配置,当一条消息写入RecordAccumulator时,会首先寻找消息分区对应的双端队列Deque,如果没有就会创建一个新的队列,然后在从队列尾部获取一个ProducerBatch,判断是否还有空间写入这个ProducerRecord,如果可以写入就直接写入到batch中即可,没有就会创建一个新的batch,并且在创建的时候,会判断这个消息的大小是否超过batch.size,如果超过就会创建对应大小的Batch,并且对应的区域不会复用,所以如果在线上系统发现每次创建的消息都比batch.size大,就需要适当调高这个参数的值,使得可以复用内存区域。

Sender线程发送消息

Sender线程从缓冲区中获取到缓存的消息之后,会转化为<分区,Deque<ProducerBatch>>,然后进一步转化为<Node,List<ProducerBatch>>的形式,Node表示Kakfa集群中的一个节点。因为网络连接是对应于某个机器而言的,也就是只关心向具体的broker发送消息,并不关心是那个分区。

然后会进一步把请求封装成<Node,Request>,然后就将每个请求发送到各个Broker上。在发送之前还会将请求放入到InFlightRequests中,InFlightRequests对象具体保存的形式是Map<NodeId,Deque<Request>>InFlightRequests的作用是用来缓存发送出去但还没有收到响应的请求。可以通过这个参数,来判断当前的网络请求。max.in.flight.requests.per.connection默认值是5,最多只能缓存5个未响应的请求,超过该参数之后就不能再发送更多的请求,除非有缓存的请求收到了响应。如果超过就说明对应的Broker负载较大或者网络连接有问题。

posted @ 2021-01-16 15:09  0xcf  阅读(124)  评论(0编辑  收藏  举报

作者:zykBlog

链接:https://www.cnblogs.com/zykBlog

来源:https://www.cnblogs.com/zykBlog

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。