美文网首页
【dubbo源码】17. 服务消费方之服务路由routes

【dubbo源码】17. 服务消费方之服务路由routes

作者: 天还下着毛毛雨 | 来源:发表于2021-07-19 22:43 被阅读0次

    前言

    当消费者启动或者注册中心的providers节点数据发生变化时,都会重新构建消费端内存中的本地服务列表。

    dubbo还提供了路由规则,决定一次 dubbo 服务调用的目标服务器,分为条件路由规则和脚本路由规则,并且支持可扩展。

    原理

    在构建服务列表中方法与invokers的映射关系:methodInvokerMap时,最终会利用Router对象,对每一个方法对应的Invokers进行一次路由过滤。

    route使用规则:

    1. API写入路由规则

      RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
      Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
      registry.register(URL.valueOf("route://0.0.0.0/com.foo.BarService?category=routers&dynamic=false&rule=" + URL.encode("host = 10.20.153.10 => host = 10.20.153.11")));
      

      具体route协议配置:
      dubbo官网-路由规则

    2. dubbo-admin界面操作

      示例 : 消费端调用UserService的getUser方法,调用ip为192.168.1.1的主机,不调用ip为192.168.1.11的主机

      image

    源码

    仍然是在RegistryDirectory类中,RegistryDirectory实现NotifyListener接口,并在消费端启动注册consumer协议之后,作为监听器注册到zk,用于监听configurators,providers,routes节点。注册监听器后会获取到这三个节点的children手动调用RegistryDirectory的notify方法调用监听器逻辑,用于服务列表的初始化。

    后续configurators,providers,routes节点发生变化,zk同样会调用监听器RegistryDirectory的notify方法,并传入最新的children,以通知消费端更新服务列表。

    dubbo-admin 添加路由规则

    image

    触发监听器的notify方法

    image

    notify(url)

    1. category为route的url放到routerUrls这个list中

      image
    2. Router对象集合的获取

      zk /dubbo/${servicePath}/routes下的每一个route协议url都会对应一个Router对象

      image image
      • ConditionRouter :条件路由规则
      • ScriptRouter : js脚本路由
      • TagRouter : 标签路由规则
      • MockInvokersSelector

      调用toRouters(routerUrls)创建route对象集合,

      image

      利用SPI工厂根据url的protocol获取对应的路由规则类实例,由于这里是condition协议,所以获取到的ConditionRouter类的实例

      image

      中途还加了MockInvokersSelector,TagRouter两种路由规则,并赋值给成员变量routers

      image
    3. 过滤方法对应的invoker列表

    获取到路由规则后,走刷新服务列表

    image

    过滤方法对应的invoker列表

    image

    初步建立方法对应invoker的映射关系

    image

    这部由于传入的方法为null,所以会原样返回invokers
    ,并建立 *和服务列表的映射

    image

    最后对每一个方法的invokers进行路由

    image

    ConditionRouter.route 过滤invokers

    ConditionRouter类介绍

    有两个成员变量存取变量

    // 匹配方法的表达式
    Map<String, MatchPair> whenCondition;
    // 方法匹配成功后的条件匹配表达式
    Map<String, MatchPair> thenCondition;
    
    image

    对应着dubbo-admin的以下配置

    ip黑名单 192.168.100.72
    作用方法 com.lb.dubbo_api.service.UserService.getUser()
    
    image
    route方法

    传入的invocation的mehtodName='getUser',路由之前有两个invoker对象,分别是以下两个服务提供者

    dubbo://192.168.31.211:20882/com.lb.dubbo_api.service.UserService?anyhost=true&application=dubbo-p&bean.name=ServiceBean:com.lb.dubbo_api.service.UserService&dubbo=2.0.2&generic=false&interface=com.lb.dubbo_api.service.UserService&methods=getUser&pid=2156&side=provider&timestamp=1626619321787
    
    dubbo://192.168.100.72:20882/com.lb.dubbo_api.service.UserService?anyhost=true&application=dubbo-p&bean.name=ServiceBean:com.lb.dubbo_api.service.UserService&dubbo=2.0.2&generic=false&interface=com.lb.dubbo_api.service.UserService&methods=getUser&pid=10228&side=provider&timestamp=1626685187324
    
    image
    1. matchWhen(url,invocation )先判断方法是否匹配,如果不配置,直接返回原Invokes,就是不做任何过滤

      image image

      从invocation拿到methodName和whenCondition进行比较,如果相同就返回true

      image
    2. matchThen 判断每一个invoker是否满足thenCondition

      image

      根据thenCondition的key取出具体要过滤的内容,再与传入的url里的相应的配置进行比较,匹配不成功就返回false,不加入到外面的结果集里

      image

      最后就只剩下192.168.31.211这个服务了

      image

      最终put到newMethodInvokerMap

      image

      所以到最后,getUser方法能调到的服务提供方经过路 由规则,会剔除掉配置的ip黑名单里的那台机器,只能 调到192.168.31.211这台机器

    相关文章

      网友评论

          本文标题:【dubbo源码】17. 服务消费方之服务路由routes

          本文链接:https://www.haomeiwen.com/subject/ggdkmltx.html