协议启动流程

DubboProtocol

DubboProtocol.export

DubboProtocol.openServer

DubboProtocol.createServer

Exchangers.bind(url, requestHandler)

new DubboProtocolServer(server)


HeaderExchanger

public class HeaderExchanger implements Exchanger {

public static final String NAME = "header";

@Override
public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
return new HeaderExchangeClient(Transporters.connect(url, new DecodeHandler(new HeaderExchangeHandler(handler))), true);
}

@Override
public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
return new HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
}

}

注意:new DecodeHandler(new HeaderExchangeHandler(handler))


1. IO线程。Netty接收消息(RPC协议解析)

NettyServerHandler.channelRead

NettyServer.received >> 父类AbstractPeer.received

MultiMessageHandler.received

HeartbeatHandler.received

AllChannelHandler.received

@Override
public void received(Channel channel, Object message) throws RemotingException {
ExecutorService executor = getPreferredExecutorService(message);
try {
executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));
} catch (Throwable t) {
if(message instanceof Request && t instanceof RejectedExecutionException){
sendFeedback(channel, (Request) message, t);
return;
}
throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
}
}

executor.execute(new ChannelEventRunnable(channel, handler, ChannelState.RECEIVED, message));

上面可以处理IO线程与RPC逻辑线程的分开。支持消息处理派发线程池。


参考资料:Dubbo 中的线程模型

<dubbo:protocol name="dubbo" dispatcher="all" threadpool="fixed" threads="100" />



2. 逻辑线程池。处理RPC:包括解析函数参数,处理service逻辑(不包括IO协议解析)

ChannelEventRunnable 处理rpc线程,每个对象处理一个(一次)rpc调用,通过线程池管理。

ChannelEventRunnable.run

DecodeHandler.received

解码消息,使用

@Override
public void received(Channel channel, Object message) throws RemotingException {
if (message instanceof Decodeable) {
decode(message);
}

if (message instanceof Request) {
decode(((Request) message).getData());
}

if (message instanceof Response) {
decode(((Response) message).getResult());
}

handler.received(channel, message);
}

rpc参数解析使用Hessian方式解码

message为DecodeableRpcInvocation

调用DecodeableRpcInvocation.decode方法

CodecSupport >> Hessian2Serialization >> Hessian2ObjectInput



参数解码完成后

调用HeaderExchangeHandler.received,然后调用 handleRequest(exchangeChannel, request);

@Override
public void received(Channel channel, Object message) throws RemotingException {
final ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
if (message instanceof Request) {
// handle request.
Request request = (Request) message;
if (request.isEvent()) {
handlerEvent(channel, request);
} else {
if (request.isTwoWay()) {
handleRequest(exchangeChannel, request);
} else {
handler.received(exchangeChannel, request.getData());
}
}
} else if (message instanceof Response) {
handleResponse(channel, (Response) message);
} else if (message instanceof String) {
if (isClientSide(channel)) {
Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl());
logger.error(e.getMessage(), e);
} else {
String echo = handler.telnet(channel, (String) message);
if (echo != null && echo.length() > 0) {
channel.send(echo);
}
}
} else {
handler.received(exchangeChannel, message);
}
}

handleRequest处理中通过future

void handleRequest(final ExchangeChannel channel, Request req) throws RemotingException {
Response res = new Response(req.getId(), req.getVersion());
if (req.isBroken()) {
Object data = req.getData();

String msg;
if (data == null) {
msg = null;
} else if (data instanceof Throwable) {
msg = StringUtils.toString((Throwable) data);
} else {
msg = data.toString();
}
res.setErrorMessage("Fail to decode request due to: " + msg);
res.setStatus(Response.BAD_REQUEST);

channel.send(res);
return;
}
// find handler by message class.
Object msg = req.getData();
try {
CompletionStage<Object> future = handler.reply(channel, msg);
future.whenComplete((appResult, t) -> {
try {
if (t == null) {
res.setStatus(Response.OK);
res.setResult(appResult);
} else {
res.setStatus(Response.SERVICE_ERROR);
res.setErrorMessage(StringUtils.toString(t));
}
channel.send(res);
} catch (RemotingException e) {
logger.warn("Send result to consumer failed, channel is " + channel + ", msg is " + e);
}
});
} catch (Throwable e) {
res.setStatus(Response.SERVICE_ERROR);
res.setErrorMessage(StringUtils.toString(e));
channel.send(res);
}
}

接下来调用到DubboProtocol.reply



线程模型

DecodeHandler.decode与DubboProtocol.reply,与Service处于相同线程。

rpc协议接收应该是使用netty的io线程。