SparkRPC源码分析之RpcRequest、RpcResponse和RpcFailure消息

SparkRPC源码分析之RpcRequest、RpcResponse和RpcFailure消息

RpcRequest

和上一个ChunkFetchRequest消息一样。入口都是从TransportRequestHandler中的hadler函数传进入。

@Override
  public void handle(RequestMessage request) {
    if (request instanceof ChunkFetchRequest) {
      processFetchRequest((ChunkFetchRequest) request);
    } else if (request instanceof RpcRequest) {
      processRpcRequest((RpcRequest) request);
    } else if (request instanceof OneWayMessage) {
      processOneWayMessage((OneWayMessage) request);
    } else if (request instanceof StreamRequest) {
      processStreamRequest((StreamRequest) request);
    } else if (request instanceof UploadStream) {
      processStreamUpload((UploadStream) request);
    } else {
      throw new IllegalArgumentException("Unknown request type: " + request);
    }
  }

然后调用processRpcRequest函数。

private void processRpcRequest(final RpcRequest req) {
    try {
      rpcHandler.receive(reverseClient, req.body().nioByteBuffer(), new RpcResponseCallback() {
        @Override
        public void onSuccess(ByteBuffer response) {
          respond(new RpcResponse(req.requestId, new NioManagedBuffer(response)));
        }

        @Override
        public void onFailure(Throwable e) {
          respond(new RpcFailure(req.requestId, Throwables.getStackTraceAsString(e)));
        }
      });
    } catch (Exception e) {
      logger.error("Error while invoking RpcHandler#receive() on RPC id " + req.requestId, e);
      respond(new RpcFailure(req.requestId, Throwables.getStackTraceAsString(e)));
    } finally {
      req.body().release();
    }
  }

这里进入方法之后首先调用的为rpcHandler.receive(……)先看recHandler是什么东西,找到它定义的地方发现它是private final RpcHandler rpcHandler,它用来处理所有RPC消息。

/**
*接收单个的rpc消息
*/
public abstract void receive(
      TransportClient client,
      ByteBuffer message,
      RpcResponseCallback callback);
/**
*接收单个的作为流接收的数据
*/
  public StreamCallbackWithID receiveStream(
      TransportClient client,
      ByteBuffer messageHeader,
      RpcResponseCallback callback) {
    throw new UnsupportedOperationException();
  }
//返回StreamManager,其中包含由TransportClient获取的关于当前流的状态。
  public abstract StreamManager getStreamManager();

//接收不需要回复的RPC消息
  public void receive(TransportClient client, ByteBuffer message) {
    receive(client, message, ONE_WAY_CALLBACK);
  }

//当与给定客户端关联的通道处于活动状态时调用。
  public void channelActive(TransportClient client) { }
//当与给定客户端关联的通道不活动时调用。
public void channelInactive(TransportClient client) { }

看完了rpcHandler之后我们接着看代码,他调用了rpcHandler函数的receive方法,这个方法有三个参数/分别为TransportClient,ByteBuffer,ResponseCallBack ,responseCallBack是用来进行回调的,无论结果是成功还是失败都会被调用一次,因此可以看到这个传参的时候起了一个匿名类,然后覆写了onSuccess和onFailure两个方法,可以看到无论是成功还是失败都会调用到respond函数。虽然其他文章介绍过它了但是再在本文介绍一遍

private ChannelFuture respond(Encodable result) {
    SocketAddress remoteAddress = channel.remoteAddress();
    return channel.writeAndFlush(result).addListener(future -> {
      if (future.isSuccess()) {
        logger.trace("Sent result {} to client {}", result, remoteAddress);
      } else {
        logger.error(String.format("Error sending result %s to %s; closing connection",
          result, remoteAddress), future.cause());
        channel.close();
      }
    });
  }

从代码中可以看到,这个方法调用的是channel.writeAndFlush方法进行响应客户端的请求。那就再看一下这个Channel是什么吧,他的定义为

private final Channel channel;

这个Channel是netty的一个组件,它用来提供一些IO操作,包含读、写、绑定操作。

RPCResponse 和RpcFailure 消息

先看代码

RPCResponseHandler 的handle方法处理的逻辑

//这里仅贴出部分代码
else if (message instanceof RpcResponse) {
      RpcResponse resp = (RpcResponse) message;
      RpcResponseCallback listener = outstandingRpcs.get(resp.requestId);
      if (listener == null) {
        logger.warn("Ignoring response for RPC {} from {} ({} bytes) since it is not outstanding",
          resp.requestId, getRemoteAddress(channel), resp.body().size());
      } else {
        outstandingRpcs.remove(resp.requestId);
        try {
          listener.onSuccess(resp.body().nioByteBuffer());
        } finally {
          resp.body().release();
        }
      }
    } else if (message instanceof RpcFailure) {
      RpcFailure resp = (RpcFailure) message;
      RpcResponseCallback listener = outstandingRpcs.get(resp.requestId);
      if (listener == null) {
        logger.warn("Ignoring response for RPC {} from {} ({}) since it is not outstanding",
          resp.requestId, getRemoteAddress(channel), resp.errorString);
      } else {
        outstandingRpcs.remove(resp.requestId);
        listener.onFailure(new RuntimeException(resp.errorString));
      }
    }

首先判断消息类型,如果为RPCResponse消息则从定义的map private final Map<Long, RpcResponseCallback> outstandingRpcs;中获取相应的 resp.requestId对应的请求callback,如果获取不到则不进行操作,如果获取到了首先从map结构中移除这个callback,然后调用RpcResponseCallback的onSuccess方法。最后释放资源resp.body().release()处理失败的消息RPCFailure也是类似不过获取到callback之后调用的是onFailure方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天心有情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值