概述
下图是Dubbo服务调用过程图:
首先由消费者服务通过代理对象Proxy发起远程调用,接着交给Client将数据编码之后经过网络传输发送到提供者服务,提供者服务接收到数据之后,先进行解码,解码之后再交给分发器Dispatcher,Dispatcher将请求派发到线程池ThreadPool,最后由线程池调用具体的服务实现类。
如果服务接口包含了返回值,那么提供者服务还需要将结果发送回给消费者服务。所以通常一个完整的请求过程包含了四个步骤:
- 消费者发送请求
- 提供者接收请求
- 提供者发送结果
- 消费者接收结果
我们将分两篇文章介绍这四部分内容,至于内容里面包含Dubbo协议相关的编解码过程将留到后面的文章单独分析。
消费者发送请求
在上一篇【Dubbo集群容错】文章里面,消费者发送请求经过了Cluster层之后将执行ClusterInvoker的doInvoke()
方法
public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers,
LoadBalance loadbalance) throws RpcException {
//......省略部分代码
Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
Result result = invoker.invoke(invocation);
}
执行invoker.invoke(invocation)
会经过一系列的过滤器,最后来到DubboInvoker的doInvoke()
方法,下图是调用栈:
那么DubboInvoker是在哪里创建的呢?答案就是通过协议Protocol创建的。在服务引用的时候会执行RegistryDirectory#refreshInvoker()
方法,该方法里面会执行toInvokers(invokerUrls)
,toInvokers(invokerUrls)
方法通过扩展接口Protocol创建Invoker实例。
invoker = new InvokerDelegate<T>(protocol.refer(serviceType, url), url, providerUrl);
因为此时的协议是dubbo,所以进入到DubboProtocol:
@Override
public <T> Invoker<T> refer(Class<T> serviceType, URL url) throws RpcException {
optimizeSerialization(url);
// create rpc invoker.
DubboInvoker<T> invoker = new DubboInvoker<T>(serviceType,
url, getClients(url), invokers);
invokers.add(invoker);
return invoker;
}
DubboInvoker继承了AbstractInvoker,我们先来介绍它的invoke()
方法:
@Override
public Result invoke(Invocation inv) throws RpcException {
//......省略部分代码
RpcInvocation invocation = (RpcInvocation) inv;
invocation.setInvoker(this);//@1
if (attachment != null && attachment.size() > 0) {
invocation.addAttachmentsIfAbsent(attachment);//@2
}
Map<String, String> context = RpcContext.getContext().getAttachments();
if (context != null) {
invocation.addAttachmentsIfAbsent(context);//@3
}
if (getUrl().getMethodParameter(invocation.getMethodName(),
Constants.ASYNC_KEY, false)) {
invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());//@4
}
RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
return doInvoke(invocation);//@5
}
代码@1:设置Invoker。
代码@2:设置attachment,RpcInvocation包含一个集合变量Map<String, String> attachments
。
代码@3:将RpcContext的attachments赋值给RpcInvocation。
代码@4:请求方式是否为异步,并将请求方式赋值给RpcInvocation。默认为同步请求。
代码@5:执行模板方法doInvoke()
交给子类DubboInvoker处理。
进入DubboInvoker的doInvoke()
方法:
@Override
protected Result doInvoke(final Invocation invocation) throws Throwable {
RpcInvocation inv = (RpcInvocation) invocation;
final String methodName = RpcUtils.getMethodName(invocation);
inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
inv.setAttachment(Constants.VERSION_KEY, version);
ExchangeClient currentClient;
if (clients.length == 1) { //@1
currentClient = clients[0];
} else {
currentClient = clients[index.getAndIncrement() % clients.length];
}
try {
boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);//@2
boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
if (isOneway) {//@3
boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
currentClient.send(inv, isSent);
RpcContext.getContext().setFuture(null);
return new RpcResult();
} else if (isAsync) {//@4
ResponseFuture future = currentClient.request(inv, timeout);
RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
return new RpcResult();
} else {//@5
RpcContext.getContext().setFuture(null);
return (Result) currentClient.request(inv, timeout).get();
}
} catch (TimeoutException e) {
throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
} catch (RemotingException e) {
throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
代码@1:赋值currentClient,实例类型是ReferenceCountExchangeClient。
代码@2:从URL获取请求方式是否是异步,是否是单向。
代码@3:处理单向请求。
代码@4:处理异步请求。
代码@5:处理正常同步请求方式。
我们先来介绍@5正常请求处理,其他两种情况后面介绍,进入ReferenceCountExchangeClient的request()
方法:
@Override
public ResponseFuture request(Object request, int timeout) throws RemotingException {
return client.request(request, timeout);
}
client的实例类型是HeaderExchangeChannel,进入HeaderExchangeChannel#request()
方法:
@Override
public ResponseFuture request(Object request, int timeout) throws RemotingException {
return channel.request(request, timeout);
}
该方法同样很简单,直接交给channel处理,channel的实例类型是HeaderExchangeChannel。另外需要说明一下的是HeaderExchangeChannel还有一个作用就是定时发送心跳给提供者服务,保活链路。逻辑在它的构造方法:
public HeaderExchangeClient(Client client, boolean needHeartbeat) {
if (client == null) {
throw new IllegalArgumentException("client == null");
}
this.client = client;
this.channel = new HeaderExchangeChannel(client);
String dubbo = client.getUrl().getParameter(Constants.DUBBO_VERSION_KEY);
this.heartbeat = client.getUrl().getParameter(Constants.HEARTBEAT_KEY,
dubbo != null && dubbo.startsWith("1.0.") ? Constants.DEFAULT_HEARTBEAT : 0);//@1
this.heartbeatTimeout = client.getUrl().
getParameter(Constants.HEARTBEAT_TIMEOUT_KEY, heartbeat * 3);//@2
if (heartbeatTimeout < heartbeat * 2) {
throw new IllegalStateException("heartbeatTimeout < heartbeatInterval * 2");
}
if (needHeartbeat) {
startHeartbeatTimer();//@3
}
}
代码@1:获取心跳包的发送频率,默认值Constants.DEFAULT_HEARTBEAT = 60 * 1000
,即一分钟发送一次。
代码@2:获取心跳超时时间,默认是心跳周期的三倍。
代码@3:执行startHeartbeatTimer()
方法,启动心跳定时任务。
private void startHeartbeatTimer() {
stopHeartbeatTimer();
if (heartbeat > 0) {
heartbeatTimer = scheduled.scheduleWithFixedDelay(
new HeartBeatTask(new HeartBeatTask.ChannelProvider() {
@Override
public Collection<Channel> getChannels() {
return Collections.<Channel>singletonList(HeaderExchangeClient.this);
}
}, heartbeat, heartbeatTimeout),
heartbeat, heartbeat, TimeUnit.MILLISECONDS);
}
}
根据heartbeat值,定时周期性执行HeartBeatTask任务:
@Override
public void run() {
long now = System.currentTimeMillis();
for (Channel channel : channelProvider.getChannels()) {
Long lastRead = (Long) channel.getAttribute(
HeaderExchangeHandler.KEY_READ_TIMESTAMP);//@1
Long lastWrite = (Long) channel.getAttribute(
HeaderExchangeHandler.KEY_WRITE_TIMESTAMP);//@2
if ((lastRead != null && now - lastRead > heartbeat)
|| (lastWrite != null && now - lastWrite > heartbeat)) {//@3
Request req = new Request();
req.setVersion("2.0.0");
req.setTwoWay(true);
req.setEvent(Request.HEARTBEAT_EVENT);
channel.send(req);
}
}
代码@1:获取连接通道最近一次读消息时间,赋值给lastRead。
代码@2:获取连接通道最近一次写消息时间,赋值给lastWrite。
代码@3:如果距离当前时间的心跳heartbeat时长内,既没有读取过消息也没有发送过消息,那么就组装请求对象Request,执行channel.send()
方法发送心跳数据。
讲解完HeaderExchangeClient的心跳处理之后,我们接着回到它的request()
方法,交给HeaderExchangeChannel处理,进入HeaderExchangeChannel的request()
方法:
@Override
public ResponseFuture request(Object request, int timeout) throws RemotingException {
if (closed) {
throw new RemotingException(this.getLocalAddress(),
null, "Failed to send request " + request + ", cause: The channel "
+ this + " is closed!");
}
// create request.
Request req = new Request(); //@1
req.setVersion("2.0.0");
req.setTwoWay(true);
req.setData(request);
DefaultFuture future = new DefaultFuture(channel, req, timeout); //@2
try {
channel.send(req); //@3
} catch (RemotingException e) {
future.cancel();
throw e;
}
return future;
}
代码@1:构建请求对象,req.setTwoWay(true)
表示请求包含返回结果(即双向请求),请求对象Request在其构造时将分配一个全局id,用于标识该请求。
public Request(long id) {
mId = id;
}
private static long newId() {
// getAndIncrement() When it grows to MAX_VALUE, it will grow to MIN_VALUE, and the negative can be used as ID
return INVOKE_ID.getAndIncrement();
}
代码@2:创建DefaultFuture对象,将请求id与Channel和DefaultFuture关联起来,目的是为了处理多线程下请求和结果映射的问题,后面会详细介绍这块内容。
private static final Map<Long, Channel> CHANNELS =
new ConcurrentHashMap<Long, Channel>();
private static final Map<Long, DefaultFuture> FUTURES =
new ConcurrentHashMap<Long, DefaultFuture>();
public DefaultFuture(Channel channel, Request request, int timeout) {
this.channel = channel;
this.request = request;
this.id = request.getId();
this.timeout = timeout > 0 ? timeout : channel.getUrl().getPositiveParameter(Constants.TIMEOUT_KEY,
Constants.DEFAULT_TIMEOUT);
// put into waiting map.
FUTURES.put(id, this);
CHANNELS.put(id, channel);
}
代码@3:执行channel.send(req)
发送请求。channel的实例类型是NettyClient。NettyClient继承了AbstractClient,AbstractClient继承了AbstractPeer。
进入AbstractPeer的send()方法:
@Override
public void send(Object message) throws RemotingException {
send(message, url.getParameter(Constants.SENT_KEY, false));
}
获取Constants.SENT_KEY,表示是否已经发送,默认值是false。
进入AbstractClient的send()
方法:
@Override
public void send(Object message, boolean sent) throws RemotingException {
if (send_reconnect && !isConnected()) {
connect();
}
Channel channel = getChannel();//@1
//TODO Can the value returned by getChannel() be null? need improvement.
if (channel == null || !channel.isConnected()) {
throw new RemotingException(this, "message can not send, because channel is closed . url:" + getUrl());
}
channel.send(message, sent);//@2
}
代码@1:获取Channel,实例类型是NettyChannel。getChannel()方法在NettyClient
@Override
protected com.alibaba.dubbo.remoting.Channel getChannel() {
Channel c = channel;
if (c == null || !c.isConnected())
return null;
return NettyChannel.getOrAddChannel(c, getUrl(), this);
}
代码@2:通过Channel发送请求数据。
进入NettyChannel的send()方法:
@Override
public void send(Object message, boolean sent) throws RemotingException {
//......省略部分代码
ChannelFuture future = channel.write(message); //@1
}
代码@1:channel的实例类型是Netty包的Channel,通过它将请求发送给提供者服务。
提供者接收请求
提供者服务在服务暴露时会通过NettyServer执行doOpen()
方法开启服务监听,并将数据处理交给NettyHandler,这块内容需要读者对Netty框架有一定的了解。进入NettyHandler的messageReceived()
方法:
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.getChannel(),
url, handler); //@1
try {
handler.received(channel, e.getMessage());//@2
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.getChannel());
}
}
代码@1:通过Netty的Channel获取NettyChannel实例。
static NettyChannel getOrAddChannel(org.jboss.netty.channel.Channel ch, URL url, ChannelHandler handler) {
if (ch == null) {
return null;
}
NettyChannel ret = channelMap.get(ch);
if (ret == null) {
NettyChannel nc = new NettyChannel(ch, url, handler);
if (ch.isConnected()) {
ret = channelMap.putIfAbsent(ch, nc);
}
if (ret == null) {
ret = nc;
}
}
return ret;
}
先从缓存channelMap获取NettyChannel,不存在就创建NettyChannel,并缓存到channelMap。
代码@2:handler的实例是NettyServer。下图NettyServer相关类的结构图:
进入AbstractPeer的received()方法:
@Override
public void received(Channel ch, Object msg) throws RemotingException {
if (closed) {
return;
}
handler.received(ch, msg);
}
handler的实例类型是MultiMessageHandler,进入它的received()方法:
@Override
public void received(Channel channel, Object message) throws RemotingException {
if (message instanceof MultiMessage) {
MultiMessage list = (MultiMessage) message;
for (Object obj : list) {
handler.received(channel, obj);
}
} else {
handler.received(channel, message);
}
}
检测message是否是MultiMessage类型,如果是执行多次handler.received(channel, obj)
,否则只执行一次,handler的实例类型是HeartbeatHandler,进入它的received()方法:
@Override
public void received(Channel channel, Object message) throws RemotingException {
//......省略部分代码
setReadTimestamp(channel);//@1
if (isHeartbeatRequest(message)) { //@2
Request req = (Request) message;
if (req.isTwoWay()) {//@3
Response res = new Response(req.getId(), req.getVersion());
res.setEvent(Response.HEARTBEAT_EVENT);
channel.send(res);
}
return;
}
if (isHeartbeatResponse(message)) {//@4
if (logger.isDebugEnabled()) {
logger.debug("Receive heartbeat response in thread " + Thread.currentThread().getName());
}
return;
}
handler.received(channel, message);//@5
}
代码@1:更新通道读取到数据时间为当前时间。
代码@2:检测消息类型是否是心跳类型,通过检测mEvent值来判断是否是心跳,后面的文章将详细介绍Dubbo协议,到时候对这块内容的理解将会更加深刻。
代码@3:判断消息类型是否是双向的,如果是双向的,构造心跳响应对象Response,执行channel.send(res)
发送回客户端。
代码@4:处理单向类型的心跳包。
代码@5:handler实例类型是AllChannelHandler。
说到AllChannelHandler我们必须提一下Dispatcher线程派发器,Dispatcher真实的职责是创建具有线程派发能力的 ChannelHandler。
@SPI(AllDispatcher.NAME)
public interface Dispatcher {
@Adaptive({Constants.DISPATCHER_KEY, "dispather", "channel.handler"})
ChannelHandler dispatch(ChannelHandler handler, URL url);
}
Dubbo 支持 5 种不同的线程派发策略:
策略 | 用途 |
---|---|
all | 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件等 |
direct | 所有消息都不派发到线程池,全部在 IO 线程上直接执行 |
message | 只有请求和响应消息派发到线程池,其它消息均在 IO 线程上执行 |
execution | 只有请求消息派发到线程池,不含响应。其它消息均在 IO 线程上执行 |
connection | 在 IO 线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池 |
AllChannelHandler在服务暴露时被创建,创建栈路线为:
new NettyServer()
-->ChannelHandlers#wrapInternal()
-->AllDispatcher#dispatch()
-->new new AllChannelHandler()
进入AllChannelHandler的received()方法:
@Override
public void received(Channel channel, Object message) throws RemotingException {
ExecutorService cexecutor = getExecutorService();//@1
try {
cexecutor.execute(new ChannelEventRunnable(channel, handler,
ChannelState.RECEIVED, message));//@2
} catch (Throwable t) {
if(message instanceof Request && t instanceof RejectedExecutionException){
Request request = (Request)message;
if(request.isTwoWay()){//@3
String msg = "Server side(" + url.getIp() + "," + url.getPort() + ") threadpool is exhausted ,detail msg:" + t.getMessage();
Response response = new Response(request.getId(), request.getVersion());
response.setStatus(Response.SERVER_THREADPOOL_EXHAUSTED_ERROR);
response.setErrorMessage(msg);
channel.send(response);
return;
}
}
throw new ExecutionException(message, channel, getClass() + " error when process received event .", t);
}
}
代码@1:获取线程池执行器ExecutorService。
代码@2:创建ChannelEventRunnable任务(state=ChannelState.RECEIVED),交给线程池处理,这种线程池通常也被称为业务线程池,将执行业务交给自线程执行,这样可以不阻塞Netty的IO线程,让Netty可以处理更多的请求。
代码@3:在线程任务执行出现异常时,如果请求是双向的,构造结果对象Response返回,状态设置为Response.SERVER_THREADPOOL_EXHAUSTED_ERROR
。
进入线程任务ChannelEventRunnable的run()方法:
@Override
public void run() {
switch (state) {
case CONNECTED:
try {
handler.connected(channel);
} catch (Exception e) {
logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel, e);
}
break;
case DISCONNECTED:
try {
handler.disconnected(channel);
} catch (Exception e) {
logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel, e);
}
break;
case SENT:
try {
handler.sent(channel, message);
} catch (Exception e) {
logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel
+ ", message is " + message, e);
}
break;
case RECEIVED:
try {
handler.received(channel, message);
} catch (Exception e) {
logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel
+ ", message is " + message, e);
}
break;
case CAUGHT:
try {
handler.caught(channel, exception);
} catch (Exception e) {
logger.warn("ChannelEventRunnable handle " + state + " operation error, channel is " + channel
+ ", message is: " + message + ", exception is " + exception, e);
}
break;
default:
logger.warn("unknown state: " + state + ", message is " + message);
}
}
ChannelEventRunnable需要处理CONNECTED(连接)、DISCONNECTED(断连)、SENT(发送消息)、RECEIVED(接收消息)、CAUGHT(异常)五个事件,handler的实例类型是DecodeHandler。执行handler.received(channel, message)
进入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);
}
首先经过decode()方法进行解码,关于编解码内容后面的文章会详细介绍,handler的实例类型是HeaderExchangeHandler,进入它的received()方法:
@Override
public void received(Channel channel, Object message) throws RemotingException {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);//@1
try {
if (message instanceof Request) {
// handle request.
Request request = (Request) message;
if (request.isEvent()) {//@2
handlerEvent(channel, request);
} else {
if (request.isTwoWay()) {//@3
Response response = handleRequest(exchangeChannel, request);
channel.send(response);
} else {//@4
handler.received(exchangeChannel, request.getData());
}
}
} else if (message instanceof Response) {//@5
handleResponse(channel, (Response) message);
} else if (message instanceof String) {//@6
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);
}
} finally {
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
}
代码@1:获取HeaderExchangeChannel实例赋值给exchangeChannel。
代码@2:处理事件类型请求。
代码@3:处理双向请求。执行handleRequest(exchangeChannel, request)
获得Response响应结果,将该结果发送回客户端。
代码@4:处理单向请求,没有返回值。
代码@5:处理响应结果。
代码@6:处理String类型数据。
进入handleRequest()
方法:
Response handleRequest(ExchangeChannel channel, Request req) throws RemotingException {
Response res = new Response(req.getId(), req.getVersion());
if (req.isBroken()) {//@1
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);
return res;
}
// find handler by message class.
Object msg = req.getData();
try {
// handle data.
Object result = handler.reply(channel, msg);//@2
res.setStatus(Response.OK);
res.setResult(result);
} catch (Throwable e) {
res.setStatus(Response.SERVICE_ERROR);
res.setErrorMessage(StringUtils.toString(e));
}
return res;
}
代码@1:处理解码失败的情况,包装状态值为Response.BAD_REQUEST的Response对象返回。
代码@2:执行handler.reply(channel, msg)
获取请求结果。handler的实例类型是DubboProtocol。
进入DubboProtocol的reply()
方法:
public Object reply(ExchangeChannel channel, Object message) throws RemotingException {
if (message instanceof Invocation) {
Invocation inv = (Invocation) message;
Invoker<?> invoker = getInvoker(channel, inv);//@1
// need to consider backward-compatibility if it's a callback
if (Boolean.TRUE.toString().equals(inv.getAttachments().get(IS_CALLBACK_SERVICE_INVOKE))) {
String methodsStr = invoker.getUrl().getParameters().get("methods");
boolean hasMethod = false;
if (methodsStr == null || methodsStr.indexOf(",") == -1) {
hasMethod = inv.getMethodName().equals(methodsStr);
} else {
String[] methods = methodsStr.split(",");
for (String method : methods) {
if (inv.getMethodName().equals(method)) {
hasMethod = true;
break;
}
}
}
if (!hasMethod) {
logger.warn(new IllegalStateException("The methodName " + inv.getMethodName()
+ " not found in callback service interface ,invoke will be ignored."
+ " please update the api interface. url is:"
+ invoker.getUrl()) + " ,invocation is :" + inv);
return null;
}
}
RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
return invoker.invoke(inv);//@2
}
throw new RemotingException(channel, "Unsupported request: "
+ (message == null ? null : (message.getClass().getName() + ": " + message))
+ ", channel: consumer: " +
+ channel.getRemoteAddress() + " --> provider: " + channel.getLocalAddress());
}
代码@1:获取Invoker实例对象:
Invoker<?> getInvoker(Channel channel, Invocation inv) throws RemotingException {
//......省略部分代码
String serviceKey = serviceKey(port, path,
inv.getAttachments().get(Constants.VERSION_KEY), inv.getAttachments().get(Constants.GROUP_KEY));
DubboExporter<?> exporter = (DubboExporter<?>) exporterMap.get(serviceKey);
return exporter.getInvoker();
}
可以看到从exporterMap将DubboExporter取出来,在【Dubbo服务暴露】文章中,服务暴露将代理对象转换为DubboExporter之后就存储到exporterMap中。
代码@2:invoker的实例类型是ProtocolFilterWrapper,经过一系列的过滤器处理后执行AbstractProxyInvoker的invoke()方法:
@Override
public Result invoke(Invocation invocation) throws RpcException {
try {
return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
} catch (InvocationTargetException e) {
return new RpcResult(e.getTargetException());
} catch (Throwable e) {
throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
执行doInvoke()
方法,此时proxy就是接口实现类的代理对象,通过代理对象调用接口实现方法:
public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf(36) < 0 ? proxy.getClass() : type);
return new AbstractProxyInvoker<T>(proxy, type, url) {
protected Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable {
return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
}
};
}
调用栈
1、消费者服务请求:
DubboInvoker
-->HeaderExchangeClient
-->HeaderExchangeChannel
-->NettyClient
-->NettyChannel
-->Channel
2、提供者服务接收:
NettyHandler
-->NettyServer
-->MultiMessageHandler(处理多数据包)
-->HeartbeatHandler(处理心跳类型数据)
-->AllChannelHandler(线程派发Handler)
-->DecodeHandler(解码处理器)
-->HeaderExchangeHandler
-->HeaderExchangeChannel
-->DubboProtocol
-->DubboExporter
-->AbstractProxyInvoker