欢迎大家关注 github.com/hsfxuebao/j… ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈
我们直接看NetworkClient 的poll()方法:
public List<ClientResponse> poll(long timeout, long now) {
//步骤三:处理响应,响应里面就会有我们需要的元数据。
handleAbortedSends(responses);
handleCompletedSends(responses, updatedNow);
/**
* 这个地方是我们在看生产者是如何获取元数据的时候,看的。
* 其实Kafak获取元数据的流程跟我们发送消息的流程是一模一样。
* 获取元数据 -> 判断网络连接是否建立好 -> 建立网络连接
* -> 发送请求(获取元数据的请求) -> 服务端发送回来响应(带了集群的元数据信息)
*/
handleCompletedReceives(responses, updatedNow);
handleDisconnections(responses, updatedNow);
handleConnections();
handleInitiateApiVersionRequests(updatedNow);
//处理超时的请求
handleTimedOutRequests(responses, updatedNow);
// invoke callbacks
for (ClientResponse response : responses) {
try {
//调用的响应的里面的我们之前发送出去的请求的回调函数
//看到了这儿,我们回头再去看一下
//我们当时发送请求的时候,是如何封装这个请求。
//不过虽然目前我们还没看到,但是我们可以大胆猜一下。
//当时封装网络请求的时候,肯定是给他绑定了一个回调函数。
response.onComplete();
} catch (Exception e) {
log.error("Uncaught error in request completion:", e);
}
}
return responses;
}
我们来看处理超时的请求handleTimedOutRequests(responses, updatedNow)
private void handleTimedOutRequests(List<ClientResponse> responses, long now) {
//获取到请求超时的主机。
List<String> nodeIds = this.inFlightRequests.getNodesWithTimedOutRequests(now, this.requestTimeoutMs);
for (String nodeId : nodeIds) {
// close connection to the node
//关闭请求超时的主机的连接
this.selector.close(nodeId);
log.debug("Disconnecting from node {} due to request timeout.", nodeId);
//我们猜应该是会去修改 连接的状态
processDisconnection(responses, nodeId, now);
}
// we disconnected, so we should probably refresh our metadata
if (!nodeIds.isEmpty())
metadataUpdater.requestUpdate();
}
private void processDisconnection(List<ClientResponse> responses, String nodeId, long now) {
//修改连接状态
connectionStates.disconnected(nodeId, now);
nodeApiVersions.remove(nodeId);
nodesNeedingApiVersionsFetch.remove(nodeId);
for (InFlightRequest request : this.inFlightRequests.clearAll(nodeId)) {
log.trace("Cancelled request {} due to node {} being disconnected", request, nodeId);
if (request.isInternalRequest && request.header.apiKey() == ApiKeys.METADATA.id)
metadataUpdater.handleDisconnection(request.destination);
else
//对这些请求进行处理
//大家会看到一个比较有意思的事
//自己封装了一个响应。这个响应里面没有服务端响应消息(服务端没给响应)
//失去连接的状态表标识为true
responses.add(request.disconnected(now));
}
}
也就是对于长时间没有接收到响应的请求,Producer会自己封装一下响应消息返回。
参考文档:
史上最详细kafka源码注释(kafka-0.10.2.0-src)
kafka技术内幕-图文详解Kafka源码设计与实现