1

接收完成的数据

broker的响应,是通过监听OP_READ事件开始的。当有read事件的时候,就会通过SelectionKey找到对应的KafkaChannel。

image.png

KafkaChannel接收到响应,就开始读取收到的数据,由于网络传输会有拆包的过程,所以接收数据的时候,就需要进粘包,kafka是这样处理的,首先定义一个消息的大小,用4个字节表示,然后后面跟着消息内容。

比如5aaaaa3bbb4cccc这种消息。

读取的时候会先拿到5,再读取aaaaa,这样第一个消息就读取到了。

然后往下读,拿到3,再读取bbb,这样第二个消息就读取到了。

然后往下读,拿到4,再读取cccc,这样第三个消息就读取到了。

读完后,把数据存在NetworkReceive,并放入KafkaChannel映射的队列中。

image.png

当处理完SelectionKey所有的事件后,就开始遍历每个KafkaChannel映射的队列,取出队列头的NetworkReceive存放在completedReceives。

image.png

不需要回调的请求

我们在发送请求的时候,会把请求进行了缓存。

有些请求是不需要返回值的,此时就直接封装一个空的ClientResponse,放入到responses列表。

并且从inFlightRequests中,移除对应的ClientRequest。

image.png

需要回调的请求

completedReceives是已经拿到的请求,当我们遍历completedReceives的时候,就会根据node的id把inFlightRequests缓存中对应的ClientRequest取出来,如果这个请求需要返回值,就会封装一个ClientResponse,放入ClientResponse列表表。

同样的,对应的ClientRequest也会从inFlightRequests中移除。

image.png

失去连接的请求

如果失去了连接,首先就会更改状态为DISCONNECTED。

image.png

然后把inFlightRequests对应的ClientRequest都新增一个disconnected为true的ClientResponse。

丢失连接后,就会要求重新拉取元数据。

image.png

连接的请求

这个操作就跟上面相反,把已经是CONNECTED的状态,修改为CONNECTED。

image.png

处理超时的请求

我们的请求都缓存在inFlightRequests中,所以直接从inFlightRequests缓存中,拿出每个node对应的ClientRequest请求,根据发送请求时间和当前的时间对比,就知道这个ClientRequest是否超时,如果超时了,就关闭对应的Channel。其他操作跟上面的失去连接的请求一样处理。

image.png

回调处理

此时,我们已经拿到了ClientResponse的列表,包括不处理的ClientResponse、超时或者端口连接disconnected为true的ClientResponse以及需要处理的ClientResponse。

此时就直接遍历ClientResponse,来处理这些回调。

image.png

如果响应里,有异常,但是可以允许重试,就会把RecordBatch重新放入batchs里。

如果有异常,但是不能重试,就把这个异常返回给我们自定义的回调函数。

如果没有异常,就封装好RecordMetadata返回给我们自定义的回调函数。


大军
847 声望183 粉丝

学而不思则罔,思而不学则殆