dubbo的服务调用-集群容错和路由负载

前面看完了服务的引用:dubbo的服务引用

在服务引用最终的就是生成了一个代理类,那么在调用某个被代理的接口时,实际上就是通过代理类去调用的,同时在实际调用之前做了容错、路由、负载等等。实际上每个调用都会从org.apache.dubbo.rpc.proxy.InvokerInvocationHandler#invoke代理
在这里插入图片描述
在这个方法中,会把我们的目标Invoker和参数封装成org.apache.dubbo.rpc.RpcInvocation#RpcInvocation(java.lang.reflect.Method, java.lang.String, java.lang.Object[]),然后会调用invoker.invoke(rpcInvocation)到达集群处理:org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker#invoke
在这里插入图片描述
这里我们看这个方法中有if else处理,这个其实就是服务降级的判断处理(https://dubbo.apache.org/zh/docs/v2.7/user/examples/service-downgrade/#m-zhdocsv27userexamplesservice-downgrade),比如mock=force:return+null表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用,用来屏蔽不重要服务不可用时对调用方的影响;mock=fail:return+null表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常,用来容忍不重要服务不稳定时对调用方的影响,具体配置方式可以在 Dubbo Admin后台动态管理 进行配置,也可以在xml文件中进行配置。实际操作是在 zk 的 /dubbo/com.xxx.xxxService/configurators 节点中添加了 override
回到这个方法里面我们依旧继续跟进会到达:org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#invoke
在这里插入图片描述

  1. 这里我们先看list(invocation);方法,跟进去继续看在这里插入图片描述
    这里开始进入目录查找directory.list(invocation),这里接下来是一个很长的调用链路,就直接标记一下走过去:org.apache.dubbo.rpc.cluster.directory.AbstractDirectory#list➡️ org.apache.dubbo.registry.integration.RegistryDirectory#doList➡️ org.apache.dubbo.rpc.cluster.RouterChain#route➡️ org.apache.dubbo.rpc.cluster.router.mock.MockInvokersSelector#route➡️ org.apache.dubbo.rpc.cluster.router.mock.MockInvokersSelector#getNormalInvokers
    这里有一个细节需要说一下,就是这个:org.apache.dubbo.rpc.cluster.RouterChain#route方法:在这里插入图片描述
    这个org.apache.dubbo.rpc.cluster.RouterChain#routers是调用时的路由,基础的是org.apache.dubbo.rpc.cluster.router.mock.MockInvokersSelector,举个例子比如在Dubbo-Admin后台页面配置了一个条件路由规则之后,那么这个routers里面就有多一个配置的路由规则进行过滤,条件路由过滤是在Router接口实现类的org.apache.dubbo.rpc.cluster.router.condition.ConditionRouter#route在这里插入图片描述
    其实跟进这个RouterChain#routers会发现他的值变更是在org.apache.dubbo.registry.integration.RegistryDirectory#notify方法里面进行的在这里插入图片描述也就是说在zk节点变更之后会通知到notify方法,然后去更新路由,那么比如在Dubbo-Admin后台配置条件路由并启用之后,就会变更zk节点,此时也回通过这个监听通知更新路由,这就是dubbo的路由更新逻辑,回到上面的流程:
    这一串调用下来,目的就是进入directory通过route获取目标的Invoker

  2. 然后回到org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#invoke,开始负载均衡:initLoadBalance(invokers, invocation)
    在这里插入图片描述
    这里是个SPI获取的动态代理类,实际获取的是org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance

  3. 然后回到org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#invoke,继续跟进到:doInvoke(invocation, invokers, loadbalance),然后默认会走到:org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke失败转移容错,当出现失败是尝试其他服务器;这里会到哪个Cluster是根据配置的决定的,其实就是集群容错的处理方式
    在这里插入图片描述
    上图这个是dubbo提供的集群容错处理方式,配置:<dubbo:service cluster="failsafe" retries="2"/> 具体这里就不写了具体集群的容错处理方式可以看官网的https://dubbo.apache.org/zh/docs/v2.7/user/examples/fault-tolerent-strategy,这里我们主要来看下快速失败和失败重试,先看失败重试:org.apache.dubbo.rpc.cluster.support.FailoverCluster➡️ org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke
    在这里插入图片描述
    可以看到这个失败重试的实现方式是先获取配置的重试次数,然后进入for循环,根据select获取到可用的一个Invoker进行远程调用,如果正常那么直接返回,出现异常那么catch之后继续下次重试知道for循环结束,这就是失败重试的容错处理。然后再看一下快速失败的处理方式:org.apache.dubbo.rpc.cluster.support.FailfastCluster➡️ org.apache.dubbo.rpc.cluster.support.FailfastClusterInvoker#doInvoke在这里插入图片描述
    可以看到快速失败非常直接,处理方式就是获取一个可用的invoker直接发起调用,失败就抛异常。

  4. 然后我们来看下负载均衡,从默认的失败重试方式中进入吧:org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke➡️ Invoker<T> invoker = select(loadbalance, invocation, copyInvokers, invoked)在这里插入图片描述
    这个方法是在从负载规则中查找一个可用的Invoker,进入doSelect(loadbalance, invocation, invokers, selected)
    在这里插入图片描述
    这个方法中看:loadbalance.select(invokers, getUrl(), invocation),跟进会到达org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance#select抽象类在这里插入图片描述
    doSelect(invokers, url, invocation)会进入其中某一个负载算法,然后得到一个结果,这些算法都是dubbo提供的,比如:RoundRobinLoadBalance权重轮训,RandomLoadBalance随机按权重设置随机概率等,具体可以看官网介绍https://dubbo.apache.org/zh/docs/v2.7/user/examples/loadbalance/,后面有空再详细写下这几个算法的具体实现,现在先以轮训为例子org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance#doSelect在这里插入图片描述
    这里我们先了解他从多个服务invokers(该方法入参)中选择一个可用的进行返回就行,这个入参invokers一个接口的多个集群提供。

然后回到了org.apache.dubbo.rpc.cluster.support.FailoverClusterInvoker#doInvoke中:
在这里插入图片描述
选择到一个Invoker之后去执行这个方法获取结果并把结果返回。

最后总结一下服务真正调用前的这些集群容错、路由负载的过程:

  1. 进入InvokerInvocationHandler#invoke
  2. directory,directory代表多个Invoker,它是动态更新的,比如对注册中心监听,如果服务节点有变化他会跟着更新
  3. router,路由,负责从多个Invoker中按照路由规则选出路由条件的子集合,这个路由可以在dubbo后台界面进行配置,用于应用隔离等
  4. Cluster,把directory中的多个Invoker封装成一个,然后调用时捕获异常,并作出异常处理,比如重试等
  5. LoadBalance,负载均衡,从多个Invoker中选择一个进行,有多重负载军和算法
  6. 把获取的Invkoer返回并执行调用获取结果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值