dubbo实现Consumer从多个group中选择指定的provider

版本

springboot :2.1.7.RELEASE

dubbo:2.7.23

curator-framework:4.0.1

背景:工作中遇到一个奇葩的需要,要求Consumer 根据参数的不同选择调用不同的group。闲话少活,下面分享下解决过程。

前提:springboot初始化时 @Reference注解的处理。简单说下,@Reference 是在初始化过程中注入进来的,在使用类的bean 初始化过程中会生成@Reference 的动态代理类,代理类生成完成后会注入进使用类里,这个动态代理类里面存储了提供者的抽象invoker列表,封装了一系列的参数。入口在bean的属性注入方法

后面依次调用会走到代理类的创建方法 

生成代理的时候,代理类会组合继承一些列功能,例如降级,容错,负载均衡,期间大量采用的dubbo的spi机制(大部分场景都可以通过spi机制定制化或者扩展功能)。同时从zk获取提供者的信息,设置zk节点变动的监听,并组装成invoker 类都是在这个时候。

刷新并获取invoker

从zk上创建节点,并获取子节点信息,也就是提供者的信息

铺垫的差不多了,下面开始具体的解决过程

猜想1:dubbo加载的时候是不是会获取所有group 的提供者?

dubbo 确实会获取所有提供者,但是组装url信息的时候会根据消费者信息过滤提供者的url,比如消费者配置的group 信息、版本信息、category信息等,因此在这个时候就已经把group给过滤掉了

猜想不成立了,能不能解决呢?还真能,dubbo有一种可合并的集群策略,具体实现类是MergeableClusterInvoker , 这个类会拿到所有 Invoker 返回的结果对象之后,会遍历每个返回结果,并调用 merger 参数指定的方法,合并这些结果值.这个功能可以通过在group的属性上设置 group='*',或者group ='a,b' 来拿到多个分组的提供者,经过验证确实可以拿到所有的提供者了。

猜想2:现在提供者拿到了,能否通过配置负载均衡的策略来实现功能呢?

通过源码和debug发现并不行,如果是单分组,代理类的invoker的包含顺序是这样的 MockClusterInvoker->FailoverClusterInvoker,如果是多分组 代理类的invoker 的顺序是这样的MockClusterInvoker->MergeableClusterInvoker->FailoverClusterInvoker,相应的代码如下

通过这段代码可以(COMMA_SPLIT_PATTERN.split(group)).length > 1 || "*".equals(group)可以知道,当group中有逗号或者* 会走下面这个代码

return doRefer(Cluster.getCluster(MergeableCluster.NAME), registry, type, url, qs);

Cluster.getCluster(MergeableCluster.NAME) 通过spi机制获取到实现类就是MergeableCluster,而单一的group 会走下面的代码,由于没有设置spi的名字,所以会获取默认的实现,就是FailoverCluster

 

而MergeableClusterInvoker实现类中,会判断是否指定合并策略,如果没有指定,就会选择第一个invoker来执行,因此修改负载均衡的策略也是不可行的,因为这个地方已经把invoker给过滤掉了,而负载均衡策略是在FailoverClusterInvoker 类中生效了,换句话说还没走到负载均衡策略的时候,invoker就已经过滤掉了。

猜想三:能否通过修改MergeableClusterInvoker 类实现功能?

MergeableClusterInvoker 类是通过 MergeableCluster 类生成的,上面已经说过MergeableCluster 是dubbo通过spi机制选择的,这个地方就给了咱们扩展的空间

当代理对象配置的是多分组的时候,这个ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap),name 是固定的也就是mergeable,因此新增一种Cluster 的配置方式是行不通,只有通过添加Wrapper 类可以修改这个spi类,然后来返回咱们自己的invoker来实现修改mergeable类,具体代码如下

经过简单的测试,完美运行啦

  • 31
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值