欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Dubbo原理(5)--服务调用流程

程序员文章站 2022-06-26 08:53:56
引用服务的流程:最终会为我们创建出一个代理对象;那么代理对象如何进行方法(远程)的调用?Dubbo官方文档里面有整个调用链的图:http://dubbo.apache.org/zh-cn/docs/dev/design.html例如:这个对象userService确实是一个代理对象,这个代理对象层层封装了各种invoker,invoker里面是我们真正要执行的功能方法;如何执行如下:public class InvokerInvocationHandler implemen...

引用服务的流程:最终会为我们创建出一个代理对象;

那么代理对象如何进行方法(远程)的调用?


Dubbo官方文档里面有整个调用链的图:http://dubbo.apache.org/zh-cn/docs/dev/design.html

Dubbo原理(5)--服务调用流程


例如:

Dubbo原理(5)--服务调用流程

这个对象userService确实是一个代理对象,这个代理对象层层封装了各种invoker,invoker里面是我们真正要执行的功能方法;


如何执行如下:

public class InvokerInvocationHandler implements InvocationHandler {

    private final Invoker<?> invoker;
    ...
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String methodName = method.getName();
        Class<?>[] parameterTypes = method.getParameterTypes();
        ...
        return invoker.invoke(new RpcInvocation(method, args)).recreate();
    }

}

1.进入要执行的方法,我们会先跳到InvokerInvocationHandler的invoke;

2.进来之后,我们会先拿到方法的信息、参数的类型信息等等;

3.下面有invoker.invoke,想要invoke执行,会把方法和参数封装成一个RPC执行的远程调用的对象;

4.invoker.invoke是如何实现的(见下)?


public class MockClusterInvoker<T> implements Invoker<T> {
    ...
    @Override
    public Result invoke(Invocation invocation) throws RpcException {
        ...
        if (value.length() == 0 || value.equalsIgnoreCase("false")) {
            //no mock
            result = this.invoker.invoke(invocation);
        } else if (value.startsWith("force")) {
            ...
        } else {
            //fail-mock
            try {
                result = this.invoker.invoke(invocation);
            } catch (RpcException e) {
                ....
            }
        }
        return result;
    }
    ...
}

1.我们首先得到的是最外层的MockClusterInvoker类的invoke方法;

2.MockClusterInvoker类的:invoke里面又封装了FailoverClusterInvoker;

3.FailoverClusterInvoker其实就是集群容错的invoke。集群容错,当我们出现失败以后,会重试,重试其他的服务器;

4.继续执行,会跳到AbstractClusterInvoker的invoke方法;


public abstract class AbstractClusterInvoker<T> implements Invoker<T> {
    ...
    @Override
    public Result invoke(final Invocation invocation) throws RpcException {
        ...
        List<Invoker<T>> invokers = list(invocation);
        if (invokers != null && !invokers.isEmpty()) {
            loadbalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(invokers.get(0).getUrl()
                    .getMethodParameter(invocation.getMethodName(), Constants.LOADBALANCE_KEY, Constants.DEFAULT_LOADBALANCE));
        }
        ...
        return doInvoke(invocation, invokers, loadbalance);
    }
    ...
}

1.AbstractClusterInvoker的invoke方法在执行的时候,会有list(invocation),这个list方法是:我们在注册中心找到到底有几个invoker来执行(eg:可能有2.0.0版本和1.0.0版本),相当于找到了2个能执行的方法;

2.接下来来获取到loadbalance负载均衡机制(我们配置的默认的负载均衡机制);

3.接下来继续doInvoke;

4.doInvoke就是FailoverClusterInvoker的doInvoke方法;


public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
    ...
    @Override
    @SuppressWarnings({"unchecked", "rawtypes"})
    public Result doInvoke(Invocation invocation, final List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
        ...
        for (int i = 0; i < len; i++) {
            ...
            Invoker<T> invoker = select(loadbalance, invocation, copyinvokers, invoked);
            invoked.add(invoker);
            ...
            try {
                Result result = invoker.invoke(invocation);
                ...
                return result;
            } catch (RpcException e) {
                if (e.isBiz()) { // biz exception.
                    throw e;
                }
                le = e;
            } catch (Throwable e) {
                le = new RpcException(e.getMessage(), e);
            } finally {
                providers.add(invoker.getUrl().getAddress());
            }
        }
        ...
    }

}

1.负载均衡拿到之后,会有select,依据负载均衡策略,随机选择一个invoker;

2.接下来有invoker.invoke,invoker里面有封装了一些filter。filter有可能在一开始代理对象里面要用invoker的时候封装一个filter(eg:要做缓存功能(结果缓存):cache;本地伪装:mock等)。接下来,invoker选中负载均衡之后,又进入了filter的环节,接下来就是各种统计信息。相当于最终,将所有filter都解除了之后,就剩下了DubboInvoker来进行远程调用;


public class DubboInvoker<T> extends AbstractInvoker<T> {
    ...
    @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) {
            currentClient = clients[0];
        } else {
            currentClient = clients[index.getAndIncrement() % clients.length];
        }
        try {
            ...
        } catch (TimeoutException e) {
            ...
        } catch (RemotingException e) {
            ...
        }
    }
    ...
}

1.DubboInvoker会拿到要执行的方法的信息,接下来会拿到客户端:ExchangeClient currentClient;

2.currentClient客户端在服务引用的时候暴露过一次(eg:我们当前要连向20882服务器);

3.方法执行超时,会报错,但是也会第二次重试等等;


---接Dubbo官方文档里面有整个调用链的图:

1.我们的代理对象proxy如果有做其他功能有filter介入;

2.我们使用cluster用来封装多个invoker的。如果有多个invoker的情况下,可以选择负载均衡机制,如果调用错了,还会有重试;

3.负载均衡在调用期间,还会有其他的filter介入,统计数据;

4.最终我们真正执行功能的是dubbo(protocol--协议)的invoker来进行调用;

5.调用的底层是client发送请求,client的底层就是netty客户端连接目标端口的服务器,来发送请求;

6.服务器请求收到数据之后,我们来解码,来整个返回,把我们整个返回数据,由代理对象交给我们;

本文地址:https://blog.csdn.net/dww161250020/article/details/107119541