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方法。