消息生产者与Kafka的交互
kafka作为消息中间件,势必会有客户端作为生产者向他发送消息,并且由于他本身是支持分布式的消息存储的,客户端在发送消息到Kafka Broker的时候,会把所有的消息分发到多个 Kafka Broker(partition)上去。
此时就会默认情况下走一个负载均衡的策略,举个例子,假设有三个partition ,发送3万条消息,就会给每个Partition分发1万条消息,这样订单数据均匀分散在了3台Broker机器上。
频繁网络通信问题
好了,现在问题来了,客户端在发送消息给Kafka Broker的时候,比如说现在要发送一个消息到Kafka上去,此时他是直接一条订单消息就对应一个网络请求,发送到一台Broker上去吗?
如果是这样做的话,那势必会导致频繁的跟一台broker进行网络通信,频繁的网络通信,每次都涉及到复杂的网络连接、传输的流程,那么进而会导致客户端性能的低下。所以Kafka当然不是这样做的。
Kafka优秀的架构设计
客户端发送消息流程
流程简述如下:
-
一条消息过来会被封装成为一个 ProducerRecord 对象。
-
拉取集群的元数据,分区的时候需要获取集群的元数据。
-
对这个对象进行序列化。(Kafka 提供了默认的序列化机制,也支持自定义序列化)
-
消息分区,也就是决定这条消息会被发送到 Kafka 服务端到哪个主题的哪个分区了。
-
分好区的消息不是直接被发送到服务端,而是放入了生产者的一个缓存里面。在这个缓存里面,多条消息会被封装成为一个批次(batch),默认一个批次的大小是 16K。
-
Sender 线程启动以后会从缓存里面去获取可以发送的批次。把一个一个批次发送到服务端。
batch机制
多条消息打包成一个batch
这个意思就是说,他会在客户端放一个内存缓冲区,每次你写一条消息先放到内存缓冲区里去,然后在内存缓冲区里,会把多个消息给打包起来成为一个batch。这样可以提高吞吐量。
而且在打包消息形成batch的时候是根据发送的Topic和Partition打包的,也就是说发送到同一个Topic的同一个Partition的消息,才会进入一个batch。
request机制
这里又出现了一个问题,我们知道一个kafka broker上面是可以有多个topic的。
现在假如说针对一个kafka broker 上的 Topic1 形成了一个batch,Topic2 也形成了一个batch,但是这两个batch其实都是发往同一个broker的,难道还是一个网络请求发送一个batch过去吗?
其实就完全没必要了,完全此时可以把多个发往同一个Broker的batch打包成一个request,然后一个request通过一次网络通信发送到那个Broker上去。
通过这种多个batch打包成一个request一次性发往Broker的方式,又进一步提高了吞吐量。