欢迎大家关注 github.com/hsfxuebao/j… ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈
Kafka源码分析12-Producer处理拆包粘包完美方案 中,我们接受到服务端响应放入暂存消息
stagedReceives 本文分析如何处理stagedReceives. 查看selector 的poll()方法:
public void poll(long timeout) throws IOException {
if (timeout < 0)
throw new IllegalArgumentException("timeout should be >= 0");
clear();
if (hasStagedReceives() || !immediatelyConnectedKeys.isEmpty())
timeout = 0;
/* check ready keys */
long startSelect = time.nanoseconds();
//从Selector上找到有多少个key注册了
int readyKeys = select(timeout);
long endSelect = time.nanoseconds();
this.sensors.selectTime.record(endSelect - startSelect, time.milliseconds());
//因为我们用场景驱动的方式
//我们刚刚确实是注册了一个key
if (readyKeys > 0 || !immediatelyConnectedKeys.isEmpty()) {
//立马就要对这个Selector上面的key要进行处理。
pollSelectionKeys(this.nioSelector.selectedKeys(), false, endSelect);
pollSelectionKeys(immediatelyConnectedKeys, true, endSelect);
}
//TODO 对stagedReceives里面的数据要进行处理
addToCompletedReceives();
long endIo = time.nanoseconds();
this.sensors.ioTime.record(endIo - endSelect, time.milliseconds());
// we use the time at the end of select to ensure that we don't close any connections that
// have just been processed in pollSelectionKeys
maybeCloseOldestConnection(endSelect);
}
我们来看addToCompletedReceives()
private void addToCompletedReceives() {
if (!this.stagedReceives.isEmpty()) {
// 如果stagedReceives集合不为空,则遍历该集合
Iterator<Map.Entry<KafkaChannel, Deque<NetworkReceive>>> iter = this.stagedReceives.entrySet().iterator();
while (iter.hasNext()) {
// 取出对应的键值对
Map.Entry<KafkaChannel, Deque<NetworkReceive>> entry = iter.next();
// 获取KafkaChannel
KafkaChannel channel = entry.getKey();
if (!channel.isMute()) {
// 判断KafkaChannel是否是mute状态,如果不是才表示此时KafkaChannel已经完成了读写操作
Deque<NetworkReceive> deque = entry.getValue();
addToCompletedReceives(channel, deque);
// 调用bytesReceived的record()方法进行记录
// 如果队列空了,移除键值对
if (deque.isEmpty())
iter.remove();
}
}
}
}
private void addToCompletedReceives(KafkaChannel channel, Deque<NetworkReceive> stagedDeque) {
// 获取队首networkReceive并添加到completedReceives
// 对于客户端来说,获取到响应
// 对于服务端来说,这接收的是请求
NetworkReceive networkReceive = stagedDeque.poll();
this.completedReceives.add(networkReceive);
// 调用bytesReceived的record()方法进行记录
this.sensors.recordBytesReceived(channel.id(), networkReceive.payload().limit());
}
在这里仅仅只会把每个连接对应的第一个响应消息会放到completedReceives里面去,放到后面去进行处理。
参考文档:
史上最详细kafka源码注释(kafka-0.10.2.0-src)
kafka技术内幕-图文详解Kafka源码设计与实现