Spring Cloud Alibaba 教程 | Dubbo(九):服务调用(上)

概述

下图是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

关注公众号了解更多原创博文

Alt

发布了122 篇原创文章 · 获赞 127 · 访问量 93万+

猜你喜欢

转载自blog.csdn.net/u010739551/article/details/104778173