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

    技术2025-01-17  52

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

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


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


    例如:

    这个对象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.服务器请求收到数据之后,我们来解码,来整个返回,把我们整个返回数据,由代理对象交给我们;

    Processed: 0.013, SQL: 9