NetworkClient分析

来源:互联网 发布:3dcg制作软件 编辑:程序博客网 时间:2024/06/06 18:25

NetworkClient是一个网络客户端实现,它可以用于生产者发送消息,也可以用于消费者消费消息以及服务器端broker之间的通信

一 核心字段

Selectable selector: 用于执行网络I/O

MetadataUpdater: 用于更新Metadata

ClusterConnectionStates connectionStates: 每一个node的连接状态

InFlightRequests: 缓存发送请求但是还没有收到响应的队列

int socketSendBuffer:发送请求的缓冲区大小

int socketReceiveBuffer: 接收响应的缓冲区大小

String clientId: 客户端唯一标示

int requestTimeoutMs:生产者等待服务器端确认消息的超时时间

 

二 重要方法

2.1 ready 检测是否可以发送请求

public booleanready(Node node, long now) {
    // 检测节点是否为空
   
if (node.isEmpty())
        throw new IllegalArgumentException("Cannotconnect to empty node "+ node);
    // 判断是否已经准备好发送请求
   
if (isReady(node,now))
        return true;
    // 检测该节点现在是否能够连接
   
if (connectionStates.canConnect(node.idString(),now))
        // 初始化一个连接
       
initiateConnect(node, now);
    return false;
}

 

public boolean isReady(Node node, long now) {    // 是否我们现在需要更新元数据以及该node是否已经可以发送请求    return !metadataUpdater.isUpdateDue(now) && canSendRequest(node.idString());}

 

2.2 send 发送请求

public void send(ClientRequest request, long now) {    // 获取发送请求的目的地    String nodeId = request.request().destination();    // 如果该节点不能发送请求,则抛出异常    if (!canSendRequest(nodeId))        throw new IllegalStateException("Attempt to send a request to node " + nodeId + " which is not ready.");    doSend(request, now);}private void doSend(ClientRequest request, long now) {    request.setSendTimeMs(now);    // 将请求添加到等待响应的inFlightRequests队列    this.inFlightRequests.add(request);    // 发送请求    selector.send(request.request());}

 

2.3 poll 进行网络I/O操作

public List<ClientResponse> poll(long timeout, long now) {    // 更新元数据请求    long metadataTimeout = metadataUpdater.maybeUpdate(now);    try {        // 执行I/O操作        this.selector.poll(Utils.min(timeout, metadataTimeout, requestTimeoutMs));    } catch (IOException e) {        log.error("Unexpected error during I/O", e);    }    // 处理完成的行为    long updatedNow = this.time.milliseconds();    List<ClientResponse> responses = new ArrayList<>();    handleCompletedSends(responses, updatedNow);// 处理completedSends队列    handleCompletedReceives(responses, updatedNow);// 处理completedReceivess队列    handleDisconnections(responses, updatedNow);//处理disconnect列表    handleConnections();//处理connect列表    handleTimedOutRequests(responses, updatedNow);// 处理InflightRquest中超时请求    // 循环调用ClientRequest的回调函数    for (ClientResponse response : responses) {        if (response.request().hasCallback()) {            try {                response.request().callback().onComplete(response);            } catch (Exception e) {                log.error("Uncaught error in request completion:", e);            }        }    }    return responses;}

 

2.4 handleCompletedSends

我们知道completedSends保存的是最近一次poll发送成功的请求

private void handleCompletedSends(List<ClientResponse> responses, long now) {    // 遍历completedSends集合    for (Send send : this.selector.completedSends()) {        // 获取指定队列的第一个元素        ClientRequest request = this.inFlightRequests.lastSent(send.destination());        if (!request.expectResponse()) {// 检测请求是否需要响应            // 不需要的话将inFlightRequests队列中的第一个请求删除            this.inFlightRequests.completeLastSent(send.destination());            // 生成ClientResponse对象添加到response集合            responses.add(new ClientResponse(request, now, false, null));        }    }}

 

2.5 handleCompletedReceives

private void handleCompletedReceives(List<ClientResponse> responses, long now) {    for (NetworkReceive receive : this.selector.completedReceives()) {        String source = receive.source();        // inFlightRequests队列中取出对应的ClientRequest        ClientRequest req = inFlightRequests.completeNext(source);        // 解析响应        Struct body = parseResponse(receive.payload(), req.request().header());        // 处理response,会更新metadata元数据,并唤醒所有等待metadata        // 更新完成的线程        if (!metadataUpdater.maybeHandleCompletedReceive(req, now, body))            // 如果不是MetadataResponse,则创建ClientResponse并添加到responses集合            responses.add(new ClientResponse(req, now, false, body));    }}

 

2.6 handleDisconnections

private void handleDisconnections(List<ClientResponse> responses, long now) {    // 更新连接状态,并清理掉inFlightRequests中断开连接的Node对应的ClientRequest    for (String node : this.selector.disconnected()) {        log.debug("Node {} disconnected.", node);        processDisconnection(responses, node, now);    }    if (this.selector.disconnected().size() > 0)        metadataUpdater.requestUpdate(); // 标识需要更新集群元数据}

 

2.7 handleConnections

private void handleConnections() {    // 遍历connect列表,将ConnectionStates中记录的连接状态修改为CONNECTed    for (String node : this.selector.connected()) {        log.debug("Completed connection to node {}", node);        this.connectionStates.connected(node);    }}

 

2.8 handleTimedOutRequests

private void handleTimedOutRequests(List<ClientResponse> responses, long now) {    // 获取inFlightRequests中超时的请求    List<String> nodeIds = this.inFlightRequests.getNodesWithTimedOutRequests(now, this.requestTimeoutMs);    // 遍历这些超时的请求    for (String nodeId : nodeIds) {        // 关闭连接        this.selector.close(nodeId);        log.debug("Disconnecting from node {} due to request timeout.", nodeId);        processDisconnection(responses, nodeId, now);    }    // 更新元数据    if (nodeIds.size() > 0)        metadataUpdater.requestUpdate();}

 

原创粉丝点击