Dubbo学习记录(十九)-服务调用【五】 - 服务消费者调用流程分析;

服务调用流程分析

普通的服务调用代码

@Component("demoServiceComponent")
public class DemoServiceComponent implements DemoService {
    
    

    @Reference
    private DemoService demoService;   //

    @Override
    public String sayHello(String name) {
    
    
        return demoService.sayHello(name);  // Invoker
    }
}

这里通过@Reference最终引入代理对象实例, Dubbo 默认使用 Javassist 框架为服务接口生成动态代理类,因此我们需要先将代理类进行反编译才能看到源码, 最终调用方法sayHello, 调用了handler#invoke, 而handler的实现类是InvokerInvocationhandler类型, 因此需要看一下InvokerInvocationHandler#invoke方法

public class proxy0 implements DC, HelloService, EchoService {
    
    
 
    // 方法数组
    public static Method[] methods;
    private InvocationHandler handler;
 
    public proxy0(InvocationHandler var1) {
    
    
        this.handler = var1;
    }
    public String sayHello(String var1) {
    
    
         // 将参数存储到 Object 数组中
        Object[] var2 = new Object[]{
    
    var1};
 
        // 调用 InvocationHandler 实现类的 invoke 方法得到调用结果
        Object var3 = this.handler.invoke(this, methods[0], var2);
 
        // 返回调用结果
        return (String)var3;
    }
    //....
    }

服务消费端调用流程

1. InvokerInvocationHandler#invoke

  • 拦截定义在 Object 类中的方法(未被子类重写),比如 wait/notify
  • 判断方法名是否为toString, 是直接调用toString方法, 不需要远程调用
  • 判断方法名是否为hashCode, 是直接调用hashCode方法 不需要远程调用
  • 判断方法名是否为equals, 是直接调用equals方法; 不需要远程调用
  • 都不是,invoker.invoke(new RpcInvocation(method, args))发起远程调用;
public class InvokerInvocationHandler implements InvocationHandler {
    
    
    private static final Logger logger = LoggerFactory.getLogger(InvokerInvocationHandler.class);
    private final Invoker<?> invoker;

    public InvokerInvocationHandler(Invoker<?> handler) {
    
    
        this.invoker = handler;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        if (method.getDeclaringClass() == Object.class) {
    
    
            return method.invoke(invoker, args);
        }
        if ("toString".equals(methodName) && parameterTypes.length == 0) {
    
    
            return invoker.toString();
        }
        if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
    
    
            return invoker.hashCode();
        }
        if ("equals".equals(methodName) && parameterTypes.length == 1) {
    
    
            return invoker.equals(args[0]);
        }

        // 这里的recreate方法很重要,他会调用AppResponse的recreate方法,
        // 如果AppResponse对象中存在exception信息,则此方法中会throw这个异常
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }
}

RpcInvocation

该类的属性包含服务调用的参数;

  • returnType 设置返回值的类型
  • methodName : 调用的方法名;
  • parameterTypes : 方法参数类型;
  • arguments : 参数值
  • invoker : 为空,没有传递;
  • attachments : 服务配置的一些相关信息,超时等;
public class RpcInvocation implements Invocation, Serializable {
    
    
    public RpcInvocation(Method method, Object[] arguments, Map<String, String> attachment) {
    
    
        this(method.getName(), method.getParameterTypes(), arguments, attachment, null);
        //设置返回值的类型;
        this.returnType = method.getReturnType();
    }
	
	public RpcInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments, Map<String, String> attachments, Invoker<?> invoker) {
    
    
        this.methodName = methodName;
        this.parameterTypes = parameterTypes == null ? new Class<?>[0] : parameterTypes;
        this.arguments = arguments == null ? new Object[0] : arguments;
        this.attachments = attachments == null ? new HashMap<String, String>() : attachments;
        this.invoker = invoker;
    }

}

因此, 服务端执行服务的时候, RpcInvocation实例包含了服务执行需要的数据;

2. MockClusterInvoker#invoke

InvokerInvocationHandler#invoke中, invoker属性类型为MockClusterInvoker实例;执行一些Mock逻辑;

  1. 判断mock配置是否为空,为空,则不执行mock逻辑, 调用下一个Invoker的invoke方法;
  2. 不为空, 且是force开头, 调用Mock逻辑doMockInvoke方法,结束远程调用;
public class MockClusterInvoker<T> implements Invoker<T> {
    
    
    private final Directory<T> directory;
    private final Invoker<T> invoker;
    @Override
    public Result invoke(Invocation invocation) throws RpcException {
    
    
        Result result = null;

        String value = directory.getUrl().getMethodParameter(invocation.getMethodName(), MOCK_KEY, Boolean.FALSE.toString()).trim();
        if (value.length() == 0 || "false".equalsIgnoreCase(value)) {
    
    
            //no mock
            result = this.invoker.invoke(invocation);
        } else if (value.startsWith("force")) {
    
    
            //force:direct mock  强制调用Mock逻辑, 直接放回数据;
            result = doMockInvoke(invocation, null);
        } else {
    
    
     		//省略部分代码
        }
        return result;
    }
}

3.1 AbstractClusterInvoker#invoke

接下来是集群容错功能的Invoker, 默认的FailoverClusterInvoker内部没有定义invoke方法,其继承了AbstractClusterInvoker类中定义了invoke方法, 因此调用的是父类的invoke方法;
干了三件事:

  1. 获取RpcContext中的attachments设置给RpcInvocation对象;
  2. 调用list方法 ,调用路由链从服务目录上,获取合适的Invoker实例invokers ;
  3. 初始化并获取负载均衡策略loadbalance;
  4. 调用子类FailoverClusterInvoker实现的方法doIoke
    @Override
    public Result invoke(final Invocation invocation) throws RpcException {
    
    
        checkWhetherDestroyed();

        // binding attachments into invocation.
        Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
        if (contextAttachments != null && contextAttachments.size() != 0) {
    
    
            ((RpcInvocation) invocation).addAttachments(contextAttachments);
        }

        List<Invoker<T>> invokers = list(invocation);
        LoadBalance loadbalance = initLoadBalance(invokers, invocation);
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);
        return doInvoke(invocation, invokers, loadbalance);
    }

3.2 FailoverClusterInvoker#doInvoke

  • 根据负载均衡策略,选出一个Invoker执行;
  • 第一次正常调用,调用失败,会重试两次, 共调用3次;
    工作流程:
  1. 获取methodName;
  2. 获取重试次数, 默认值为2; 会进行+1操作, 因此需要把第一次调用算进去;
  3. 调用select方法, 负载均衡选出一个服务;
  4. 调用下一个invoker#invoke方法;
public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
    
    
    public FailoverClusterInvoker(Directory<T> directory) {
    
    
        super(directory);
    }
    @Override
    @SuppressWarnings({
    
    "unchecked", "rawtypes"})
    public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
    
    
        List<Invoker<T>> copyInvokers = invokers;
        String methodName = RpcUtils.getMethodName(invocation);
        int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
        if (len <= 0) {
    
    
            len = 1;
        }
        // retry loop.
        RpcException le = null; // last exception.
        List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
        Set<String> providers = new HashSet<String>(len);
        for (int i = 0; i < len; i++) {
    
    
            if (i > 0) {
    
    
                checkWhetherDestroyed();
                copyInvokers = list(invocation);
                // check again
                checkInvokers(copyInvokers, invocation);
            }
            Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked);
            invoked.add(invoker);
            RpcContext.getContext().setInvokers((List) invoked);
            try {
    
    
                Result result = invoker.invoke(invocation);
				//省略部分代码
                return result;
            } catch (RpcException e) {
    
    
            } catch (Throwable e) {
    
    
                le = new RpcException(e.getMessage(), e);
            } finally {
    
    
                providers.add(invoker.getUrl().getAddress());
            }
        }
		//异常处理
    }

}

下一个Invoker的类型为RegistryDirectory$InvokerDelegate类, 调用InvokerDelegate#invoke方法

4 InvokerDelegate#invoke

InvokerDelegate类没有定义invoke方法, 其继承了InvokerWrapper,其定义了invoke方法;
这个代理对象invoke,啥都没干;

private static class InvokerDelegate<T> extends InvokerWrapper<T> {
    
    
        private URL providerUrl;

        public InvokerDelegate(Invoker<T> invoker, URL url, URL providerUrl) {
    
    
            super(invoker, url);
            this.providerUrl = providerUrl;
        }

        public URL getProviderUrl() {
    
    
            return providerUrl;
        }
}

public class InvokerWrapper<T> implements Invoker<T> {
    
    

    private final Invoker<T> invoker;
    @Override
    public Result invoke(Invocation invocation) throws RpcException {
    
    
        return invoker.invoke(invocation);
    }
}

5 CallbackRegistrationInvoker#invoke

  • ProtocolFilterWrapper生成的Invoker;
  • 会调用执行过滤器链, 执行完执行完得到结果;
  • 拿到结果后,会获取ListenableFilter中的listener,执行listener的onResponse方法
    static class CallbackRegistrationInvoker<T> implements Invoker<T> {
    
    

        private final Invoker<T> filterInvoker;
        private final List<Filter> filters;

        @Override
        public Result invoke(Invocation invocation) throws RpcException {
    
    
            // 执行过滤器链
            Result asyncResult = filterInvoker.invoke(invocation);

            // 过滤器都执行完了之后,回调每个过滤器的onResponse或onError方法
            asyncResult = asyncResult.whenCompleteWithContext((r, t) -> {
    
    
                for (int i = filters.size() - 1; i >= 0; i--) {
    
    
                    Filter filter = filters.get(i);
                    // onResponse callback
                    if (filter instanceof ListenableFilter) {
    
    
                        Filter.Listener listener = ((ListenableFilter) filter).listener();
                        if (listener != null) {
    
    
                            if (t == null) {
    
    
                                listener.onResponse(r, filterInvoker, invocation);
                            } else {
    
    
                                listener.onError(t, filterInvoker, invocation);
                            }
                        }
                    } else {
    
    
                        filter.onResponse(r, filterInvoker, invocation);
                    }
                }
            });
            return asyncResult;
        }
}

5 ConsumerContextFilter#invoke

设置上下文参数;

  • 本地地址localAddress;
  • 远程调用地址remoteAddress
  • 远程应用名称remoteApplicationName;
  • 服务参数attachments;
@Activate(group = CONSUMER, order = -10000)
public class ConsumerContextFilter extends ListenableFilter {
    
    
    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    
    
        // 设置RpcContext参数
        RpcContext.getContext()
                .setInvoker(invoker)
                .setInvocation(invocation)
                .setLocalAddress(NetUtils.getLocalHost(), 0)
                .setRemoteAddress(invoker.getUrl().getHost(), invoker.getUrl().getPort())
                .setRemoteApplicationName(invoker.getUrl().getParameter(REMOTE_APPLICATION_KEY))
                .setAttachment(REMOTE_APPLICATION_KEY, invoker.getUrl().getParameter(APPLICATION_KEY));
        if (invocation instanceof RpcInvocation) {
    
    
            ((RpcInvocation) invocation).setInvoker(invoker);
        }
        try {
    
    
            RpcContext.removeServerContext();
            return invoker.invoke(invocation);
        } finally {
    
    
            RpcContext.removeContext();
        }
    }

    static class ConsumerContextListener implements Listener {
    
    
        @Override
        public void onResponse(Result appResponse, Invoker<?> invoker, Invocation invocation) {
    
    
            RpcContext.getServerContext().setAttachments(appResponse.getAttachments());
        }
		//....
    }
}    

6. FutureFilter#invoke

  1. 调用fireInvokeCallback判断是否有回调方法,有就触发回调方法
  2. 调用下一个Invoke#invoke处理;
@Activate(group = CommonConstants.CONSUMER)
public class FutureFilter extends ListenableFilter {
    
    
    @Override
    public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException {
    
    
        fireInvokeCallback(invoker, invocation);
        // need to configure if there's return value before the invocation in order to help invoker to judge if it's
        // necessary to return future.
        return invoker.invoke(invocation);
    }
}

7. ListenerInvokerWrapper#invoke

啥都没干,调用下一个Invoker#invoke方法;

public class ListenerInvokerWrapper<T> implements Invoker<T> {
    
    
    private final Invoker<T> invoker;
    private final List<InvokerListener> listeners;
    @Override
    public Result invoke(Invocation invocation) throws RpcException {
    
    
        // AsyncToSyncInvoker
        return invoker.invoke(invocation);
    }

}

8. AsyncToSyncInvoker#invoke

public class AsyncToSyncInvoker<T> implements Invoker<T> {
    
    

    private Invoker<T> invoker;

    public AsyncToSyncInvoker(Invoker<T> invoker) {
    
    
        this.invoker = invoker;
    }

    @Override
    public Class<T> getInterface() {
    
    
        return invoker.getInterface();
    }

    @Override
    public Result invoke(Invocation invocation) throws RpcException {
    
    
        // 异步转同步

        Result asyncResult = invoker.invoke(invocation);  // AsyncRpcResult--->CompletableFuture

        try {
    
    
            // 如果invocation指定是同步的,则阻塞等待结果
            if (InvokeMode.SYNC == ((RpcInvocation) invocation).getInvokeMode()) {
    
    
                asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
            }
        } catch (InterruptedException e) {
    
    
  		//..异常处理
        } catch (Throwable e) {
    
    
            throw new RpcException(e.getMessage(), e);
        }
        return asyncResult;
    }
}

9. AbstractInvoker.invoke(invocation)

主要调用DubboInvoker的doInvoke方法,如果doInvoker方法出现了异常,会进行包装,包装成AsyncRpcResult

    @Override
    public Result invoke(Invocation inv) throws RpcException {
    
    
        RpcInvocation invocation = (RpcInvocation) inv;
        invocation.setInvoker(this);

        invocation.setInvokeMode(RpcUtils.getInvokeMode(url, invocation));
        RpcUtils.attachInvocationIdIfAsync(getUrl(), invocation);

        try {
    
    
            return doInvoke(invocation);
        } catch (InvocationTargetException e) {
    
     // biz exception
            Throwable te = e.getTargetException();
            if (te == null) {
    
    
                return AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
            } else {
    
    
                if (te instanceof RpcException) {
    
    
                    ((RpcException) te).setCode(RpcException.BIZ_EXCEPTION);
                }
                return AsyncRpcResult.newDefaultAsyncResult(null, te, invocation);
            }
        } catch (RpcException e) {
    
    
            if (e.isBiz()) {
    
    
                return AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
            } else {
    
    
                throw e;
            }
        } catch (Throwable e) {
    
    
            return AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
        }
    }

10. DubboInvoker#doInvoke

  • 从clients轮询出一个client进行数据发送,如果配置了不关心结果,则调用ReferenceCountExchangeClient的send方法,否则调用ReferenceCountExchangeClient的request方法;
  • asyncRpcResult.subscribeTo(responseFuture) : 响应结果结果responseFuture和异步RPC结果进行绑定, 当responseFuture拿到返回值后, 就会将返回结果内容 设置给asyncRpcResult异步RPC结果
@Override
    protected Result doInvoke(final Invocation invocation) throws Throwable {
    
    
        RpcInvocation inv = (RpcInvocation) invocation;
        final String methodName = RpcUtils.getMethodName(invocation);
        inv.setAttachment(PATH_KEY, getUrl().getPath());
        inv.setAttachment(VERSION_KEY, version);

        // 一个DubboInvoker对象可能并发的同时去调用某个服务
        // 那么单独的一次调用都需要一个单独的client去发送请求
        // 所以这里会去选择使用本次调用该使用哪个client
        ExchangeClient currentClient;
        if (clients.length == 1) {
    
    
            currentClient = clients[0];
        } else {
    
    
            // 轮询使用clients
            currentClient = clients[index.getAndIncrement() % clients.length];
        }

        try {
    
    
            // isOneway为true,表示请求不需要拿结果
            boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
            // 拿当前方法的所配置的超时时间,默认为1000,1秒
            int timeout = getUrl().getMethodPositiveParameter(methodName, TIMEOUT_KEY, DEFAULT_TIMEOUT);
            if (isOneway) {
    
    
                boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
                currentClient.send(inv, isSent);
                // 生成一个默认的值的结果,value=null
                return AsyncRpcResult.newDefaultAsyncResult(invocation);
            } else {
    
    
                AsyncRpcResult asyncRpcResult = new AsyncRpcResult(inv);
                // 异步去请求,得到一个CompletableFuture
                CompletableFuture<Object> responseFuture = currentClient.request(inv, timeout);

                // responseFuture会完成后会调用asyncRpcResult中的方法,这里并不会阻塞,如果要达到阻塞的效果在外层使用asyncRpcResult去控制
                asyncRpcResult.subscribeTo(responseFuture);
                // save for 2.6.x compatibility, for example, TraceFilter in Zipkin uses com.alibaba.xxx.FutureAdapter
                FutureContext.getContext().setCompatibleFuture(responseFuture);
                return asyncRpcResult;
            }
        } 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);
        }
    }

AsyncRpcResult

异步调用结果对象;

  • 包含调用参数invocation, 与上下文属性;
  • 继承AbstractResult 抽象类, 其继承了CompletableFuture类,代表是一个异步类对象;
public abstract class AbstractResult extends CompletableFuture<Result> implements Result {
    
    
}

public class AsyncRpcResult extends AbstractResult {
    
    
    private RpcContext storedContext;
    private RpcContext storedServerContext;

    private Invocation invocation;

    public AsyncRpcResult(Invocation invocation) {
    
    
        this.invocation = invocation;
        this.storedContext = RpcContext.getContext();
        this.storedServerContext = RpcContext.getServerContext();
    }
}

11. ReferenceCountExchangeClient#request

啥都没干,调用下一层的client处理;

final class ReferenceCountExchangeClient implements ExchangeClient {
    
    
    private final Client client;
    @Override
    public CompletableFuture<Object> request(Object request, int timeout) throws RemotingException {
    
    
        return channel.request(request, timeout);
        }
}

12. HeaderExchangeClient#request

没做什么事情

public class HeaderExchangeClient implements ExchangeClient {
    
    

    private final Client client;
    private final ExchangeChannel channel;

    @Override
    public CompletableFuture<Object> request(Object request, int timeout) throws RemotingException {
    
    
        return channel.request(request, timeout);
        }
}

13.HeaderExchangeChannel#request

创建请求实例req, 设置版本Dubbo版本信息, 同步调用, 请求数据request(RpcInvocation实例)
创建DefaultFuture实例, 内部绑定请求Id, 会将DefaultFuture实例为value, 请求id为key,放入缓存FUTURES中; 当HeaderExchangeHandler接收到返回结果后, 会从FUTURES根据请求ID拿出DefaultFuture实例,然后返回Response。

    @Override
    public CompletableFuture<Object> request(Object request, int timeout) throws RemotingException {
    
    
        // create request.
        Request req = new Request();
        req.setVersion(Version.getProtocolVersion());
        req.setTwoWay(true);
        req.setData(request);
        DefaultFuture future = DefaultFuture.newFuture(channel, req, timeout);
        try {
    
    
            channel.send(req);
        } catch (RemotingException e) {
    
    
            future.cancel();
            throw e;
        }
        return future;
    }

14. AbstractPeer.send(Object message)

从url中获取send参数,默认为false

public abstract class AbstractPeer implements Endpoint, ChannelHandler {
    
    
    private final ChannelHandler handler;
    private volatile URL url;
    @Override
    public void send(Object message) throws RemotingException {
    
    
        send(message, url.getParameter(Constants.SENT_KEY, false));
    }
}

15. AbstractClient#send(Object message, boolean sent)

没做什么;

16. NettyChannel#send

  • 调用NioSocketChannel#send发送数据,调用NioSocketChannel的writeAndFlush发送数据
  • 然后判断send如果是true,那么则阻塞url中指定的timeout时间,
  • 因为如果send是false,在HeaderExchangeChannel中会阻塞timeout时间
  • 判断future是否存在异常,存在则抛出异常;
final class NettyChannel extends AbstractChannel {
    
    
    private static final ConcurrentMap<Channel, NettyChannel> CHANNEL_MAP = new ConcurrentHashMap<Channel, NettyChannel>();
    private final Channel channel;

    @Override
    public void send(Object message, boolean sent) throws RemotingException {
    
    
        // whether the channel is closed
        super.send(message, sent);
        boolean success = true;
        int timeout = 0;
        try {
    
    
            ChannelFuture future = channel.writeAndFlush(message);
            if (sent) {
    
    
                // wait timeout ms
                timeout = getUrl().getPositiveParameter(TIMEOUT_KEY, DEFAULT_TIMEOUT);
				//阻塞一定时间
                success = future.await(timeout);
            }
            Throwable cause = future.cause();
            if (cause != null) {
    
    
                throw cause;
            }
        } catch (Throwable e) {
    
    
            throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
        }
        if (!success) {
    
    
            throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress()
                    + "in timeout(" + timeout + "ms) limit");
        }
    }
}

17. NioSocketChannel.writeAndFlush(Object msg)

最底层的Netty非阻塞式的发送数据;属于netty的内容了。

猜你喜欢

转载自blog.csdn.net/yaoyaochengxian/article/details/124569408