当前位置: 移动技术网 > IT编程>网页制作>HTML > Dubbo原理(5)--服务调用流程

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

2020年07月09日  | 移动技术网IT编程  | 我要评论

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

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


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

/dev-guide/images/dubbo-extension.jpg


例如:

这个对象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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网