源码学习dubbo3.x的运行期流量调度

前言

  1. dubbo官网可知Dubbo提供了六大核心能力,运行期流量调度就是其中一种。
  2. 运行期流量调度:内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。
  3. 下面我们通过源码调式探索,运行期流量调度是怎样实现的?

Dubbo如何触发路由规则

  1. 通过前面描述可知,运行期流量调度时通过配置路由规则实现的
  2. 具体如何配置路由规则,参照官网《路由规则》说明
    2.1 路由规则包括入站流量的规则(VirtualService)和目标地址规则(DestinationRule)
  3. 通过《dubbo3.x消费端源码浅析以及Triple协议的实现》文章中了解到Dubbo远程调用主要步骤如下
    // AbstractClusterInvoker#invoke
    public Result invoke(final Invocation invocation) throws RpcException {
    	// 根据调用信息获取Invoker列表(通过流量规则进行路由选择)
    	List<Invoker<T>> invokers = list(invocation);
    	// 在Invoker列表中进行负载
    	LoadBalance loadbalance = initLoadBalance(invokers, invocation);
    	return doInvoke(invocation, invokers, loadbalance);
    }
    

路由规则过滤

  1. 路由规则过滤调用栈入口如下
    在这里插入图片描述
  2. 主要关注MeshRuleRouter#route
    2.1 在dubbo源码中没有找到相应的配置demo,但是有MeshRuleRouter的测试类MeshRuleRouterTest,我们就跑一下测试用例(route方法)了解其内部运行机制
    public <T> RouterResult<Invoker<T>> route(List<Invoker<T>> invokers, URL url,
                                              Invocation invocation, boolean needToPrintMessage) throws RpcException {
         // 根据调用信息(服务名、方法)获取具体的流量规则列表
    	List<DubboRouteDestination> routeDestination = getDubboRouteDestination(invocation);
    	// 如果没配入口流量规则或者不匹配,则返回全部的invoker
    	if (routeDestination == null) {
            return new RouterResult<>(invokers);
        }else{
        	// 随机选择一个入口流量规则
    		DubboRouteDestination dubboRouteDestination = routeDestination.get(ThreadLocalRandom.current().nextInt(routeDestination.size()));
    		// DubboDestination:用来描述路由流量的目标地址
    		DubboDestination dubboDestination = dubboRouteDestination.getDestination();
    		// subset :地址列表
    		String subset = dubboDestination.getSubset();
    		
    		List<Invoker<?>> result;
    		Map<String, List<Invoker<?>>> subsetMapCopy = this.subsetMap;
    		do {
    			// 获取地址列表对应的Invoker列表(subsetMapCopy内容是根据目标地址规则匹配出来的)
    			result = subsetMapCopy.get(subset);
    			if (CollectionUtils.isNotEmpty(result)) {
                  	return new RouterResult<>((List) result);
               	}
               	/**
               	  * fallback 处理原则(摘抄于官网描述)
               	  * 由于多个 router 之间多个条件组件之后,很容易出现地址被筛选为空的情	
               	  * 况,那么我们需要针对这情况进行 fallback 处理,保证业务在正确性的前提
               	  * 下,能够顺利找到有效地址
               	  * */
               	dubboRouteDestination = dubboDestination.getFallback();
                if (dubboRouteDestination == null) {
                    break;
                }
                dubboDestination = dubboRouteDestination.getDestination();
                subset = dubboDestination.getSubset();
    		}while(true)
    		
    	}
    }
    

    2.2 跟了流量规则路由的代码后,总结一下
    (1)根据调用信息的服务名方法信息匹配符合条件的流量的实际目标地址(入站流量的规则)
    (2)根据配置的服务标签匹配符合条件的服务参数的invoker列表(目标地址规则)
    (3)入站流量规则的spec.dubbo.routedetail.route.destination.subnet与目标地址规则的spec.subsets.name一一对应,找到符合的invoker列表

灰度发布

  1. 什么是灰度发布?
    1.1 百度百科的解释:灰度发布(又名金丝雀发布)是指在黑与白之间,能够平滑过渡的一种发布方式。在其上可以进行A/B testing,即让一部分用户继续用产品特性A,一部分用户开始用产品特性B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B上面来。灰度发布可以保证整体系统的稳定,在初始灰度的时候就可以发现、调整问题,以保证其影响度

  2. Dubbo对灰度的支持
    2.1 实现灰度发布,在请求到达服务提供前,能将请求按预设的规则去访问目标服务提供者
    2.2 通过上面可知,invocaruib会先经过一个路由器链并返回一组合适的目标服务器地址列表,然后在这些服务器地址中做负载均衡

束语

  1. 本篇文章主要分析Dubbo3.x的路由规则,了解其内部是如何路由选择的。
  2. 了解灰度发布的概念,知道Dubbo3.x是如何支持灰度发布的
  3. 突然发现标题写的是运行期流量调度,那怎样运行时修改调度规则呢?
    3.1 在跟代码时发现,在启动时会初始化MeshAppRuleListener
    3.2 MeshAppRuleListener的process处理数据变更

版权声明:本文为weixin_40803011原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。