jannal(无名小宝)

没有失败,只有缓慢的成功

导航

Dubbo之路由与配置规则(2.6.x)

Dubbo版本

  1. Dubbo 2.6.7版本
  2. 官方文档旧路由规则文档中【标签路由规则】存在描述错误。 https://github.com/apache/dubbo-website/issues/1022这是我提交的issue

简介

  1. 路由规则决定Dubbo调用哪些目标服务器,分为条件路由规则和脚本路由规则

  2. 一般由监控中心(Dubbo-Admin)或者治理中心来配置路由规则

  3. 向注册中心写入路由规则的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")));
    
  4. URL参数说明

    参数 描述 是否必填
    route:// 表示路由规则的类型,支持条件路由规则和脚本路由规则。可扩展
    0.0.0.0 表示对所有 IP 地址生效,如果只想对某个 IP 的生效,请填入具体 IP
    com.foo.BarService 表示只对指定服务生效
    group=foo 对指定服务的指定group生效,不填表示对未配置group的指定服务生效
    version=1.0 对指定服务的指定version生效,不填表示对未配置version的指定服务生效
    category=routers 表示该数据为动态配置类型
    dynamic=false 表示该数据为持久数据,当注册方退出时,数据依然保存在注册中心
    enabled=true 覆盖规则是否生效,可不填,缺省生效
    force=false 当路由结果为空时,是否强制执行,如果不强制执行,路由结果为空的路由规则将自动失效,可不填,缺省为 false
    runtime=false 是否在每次调用时执行路由规则,否则只在提供者地址列表变更时预先执行并缓存结果,调用时直接从缓存中获取路由结果。如果用了参数路由,必须设为 true,需要注意设置会影响调用的性能,可不填,缺省为 false
    priority=1 路由规则的优先级,用于排序,优先级越大越靠前执行。默认是0
    rule=URL.encode("host = 10.20.153.10 => host = 10.20.153.11") 路由规则的内容

条件路由

  1. 规则:consumer匹配条件 => provider匹配条件

    • => 之前的为消费者匹配条件,所有参数和消费者的 URL 进行对比,当消费者满足匹配条件时,对该消费者执行后面的过滤规则。
    • => 之后为提供者地址列表的过滤条件,所有参数和提供者的 URL 进行对比,消费者最终只拿到过滤后的地址列表。
    • 如果匹配条件为空,表示对所有消费方应用,如:=> host != 10.20.153.11
    • 如果过滤条件为空,表示禁止访问,如:host = 10.20.153.10 =>
  2. 表达式

    • 参数支持:

      • 服务调用信息,如:method, argument 等,暂不支持参数路由

      • URL 本身的字段,如:protocol, host, port 等

      • 以及 URL 上的所有参数,如:application, organization 等

    • 条件支持:

      • 等号 = 表示"匹配",如:host = 10.20.153.10
      • 不等号 != 表示"不匹配",如:host != 10.20.153.10
    • 值支持:

      • 以逗号 , 分隔多个值,如:host != 10.20.153.10,10.20.153.11
      • 以星号 * 结尾,表示通配,如:host != 10.20.*
      • 以美元符 $ 开头,表示引用消费者参数,如:host = $host
  3. 示例

    1. 排除IP
    => host != 172.22.3.91
    
    2. 白名单(一个服务只能有一条白名单规则,否则两条规则交叉,就都被筛选掉了)
    host != 10.20.153.10,10.20.153.11 =>
    
    3. 黑名单:
    host = 10.20.153.10,10.20.153.11 =>
    
    4. 服务寄宿在应用上,只暴露一部分的机器,防止整个集群挂掉:
    => host = 172.22.3.1*,172.22.3.2*
    
    5. 为重要应用提供额外的机器:
    application != kylin => host != 172.22.3.95,172.22.3.96
    
    6. 读写分离:
    method = find*,list*,get*,is* => host = 172.22.3.94,172.22.3.95,172.22.3.96
    method != find*,list*,get*,is* => host = 172.22.3.97,172.22.3.98
    
    7.前后台分离:
    application = bops => host = 172.22.3.91,172.22.3.92,172.22.3.93
    application != bops => host = 172.22.3.94,172.22.3.95,172.22.3.96
    
    8. 隔离不同机房网段:
    host != 172.22.3.* => host != 172.22.3.*
    
    9. 提供者与消费者部署在同集群内,本机只访问本机的服务:
    => host = $host
    
  4. 端口

    1. 只调用指定端口的服务
    => port = 20881
    => port = 20881,20882
    
    2. ip和端口
    => port = 20881,20882 & host = 172.16.117.33 
    

标签路由

  1. 当应用选择装配标签路由(TagRouter)之后,一次 dubbo 调用能够根据请求携带的 tag 标签智能地选择对应 tag 的服务提供者进行调用。

    • dubbo.tag=provder1 时优先选择 tag=provider1 的 provider。若集群中不存在与请求标记对应的服务,可以降级请求tag=null 的 provider,即默认 provider。
    • dubbo.tag=null时,只会匹配 tag=null 的 provider。即使集群中存在可用的服务,若 tag 不匹配就无法调用,这与规则1不同,携带标签的请求可以降级访问到无标签的服务,但不携带标签/携带其他种类标签的请求永远无法访问到其他标签的服务
  2. 生产者配置

    1. 应用设置标签
    <dubbo:application name="xml-demo-provider">
        <dubbo:parameter key="qos.enable" value="false"/>
        <dubbo:parameter key="dubbo.tag" value="provder1"/>
    </dubbo:application>
    
    2. provider设置标签
    <dubbo:provider tag="provder2"></dubbo:provider>
    
  3. 消费者配置

    //dubbo.tag
    RpcContext.getContext().setAttachment(Constants.TAG_KEY, "provder1");
    //dubbo.force.tag 如果设置为true,则不降级,否则降级为默认provider
    RpcContext.getContext().setAttachment(Constants.FORCE_USE_TAG, "provder1");
    
  4. 源码分析TagRouter#route

    @Override
    public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
        // filter
        List<Invoker<T>> result = new ArrayList<Invoker<T>>();
        // Dynamic param 获取dubbo.tag
        String tag = RpcContext.getContext().getAttachment(Constants.TAG_KEY);
        // Tag request
        if (!StringUtils.isEmpty(tag)) {
            // Select tag invokers first
            for (Invoker<T> invoker : invokers) {
                if (tag.equals(invoker.getUrl().getParameter(Constants.TAG_KEY))) {
                    result.add(invoker);
                }
            }
        }
        // If Constants.REQUEST_TAG_KEY unspecified or no invoker be selected, downgrade to normal invokers
        if (result.isEmpty()) {
            // Only forceTag = true force match, otherwise downgrade
            //如果dubbo.force.tag=true则不降级,否则降级为默认provider
            String forceTag = RpcContext.getContext().getAttachment(Constants.FORCE_USE_TAG);
            if (StringUtils.isEmpty(forceTag) || "false".equals(forceTag)) {
                for (Invoker<T> invoker : invokers) {
                    if (StringUtils.isEmpty(invoker.getUrl().getParameter(Constants.TAG_KEY))) {
                        result.add(invoker);
                    }
                }
            }
        }
        return result;
    }
    

配置规则

  1. 覆盖规则是 Dubbo 设计的在无需重启应用的情况下,动态调整 RPC 调用行为的一种能力。可以通过监控中心或者治理中心向注册中心写入动态配置覆盖规则

    RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
    Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
    registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&timeout=1000"));
    
  2. URL参数说明

    参数 描述 是否必填
    override:// 表示数据采用覆盖方式,支持 overrideabsent
    0.0.0.0 表示对所有 IP 地址生效,如果只想覆盖某个 IP 的数据,请填入具体 IP
    com.foo.BarService 表示只对指定服务生效
    category=configurators 表示该数据为动态配置类型
    dynamic=false 表示该数据为持久数据,当注册方退出时,数据依然保存在注册中心
    enabled=true 覆盖规则是否生效,缺省生效
    application=foo 表示只对指定应用生效,不填,表示对所有应用生效。
    timeout=1000 表示将满足以上条件的 timeout 参数的值覆盖为 1000。如果想覆盖其它参数,直接加在 override 的 URL 参数上
  3. 示例

    • 禁用提供者:(通常用于临时踢除某台提供者机器,相似的,禁止消费者访问请使用路由规则)

      override://10.20.153.10/com.foo.BarService?category=configurators&dynamic=false&disbaled=true
      
    • 调整权重:(通常用于容量评估,缺省权重为 100)

      override://10.20.153.10/com.foo.BarService?category=configurators&dynamic=false&weight=200
      
    • 调整负载均衡策略:(缺省负载均衡策略为 random)

      override://10.20.153.10/com.foo.BarService?category=configurators&dynamic=false&loadbalance=leastactive
      
    • 服务降级:(通常用于临时屏蔽某个出错的非关键服务)

      override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null
      

posted on 2022-02-08 10:34  jannal  阅读(1437)  评论(0编辑  收藏  举报