Dubbo 服务路由

本文详细介绍了Dubbo服务路由的三种实现方式:条件路由、标签路由和脚本路由,包括它们的工作原理、配置示例和应用场景,强调了如何通过这些策略进行流量控制和实例选择。
摘要由CSDN通过智能技术生成

服务路由

1、服务路由是什么?

服务路由包含一条路由规则,路由规则决定了服务消费者的调用目标,即规定了服务消费者可调用哪些服务提供者。Dubbo 目前提供了三种服务路由实现,分别为条件路由 ConditionRouter、脚本路由 ScriptRouter 和标签路由 TagRouter。其中条件路由是我们最常使用的

2、条件路由

条件路由规则将符合特定条件的请求转发到特定的地址实例子集上。规则首先对发起流量的请求参数进行匹配,符合匹配条件的请求将被转发到包含特定实例地址列表的子集。

条件路由的格式:

[服务消费者匹配条件] => [服务提供者匹配条件]
host = 10.20.150.30 => host = 10.20.150.31

该条规则表示 IP 为 10.20.150.30 的服务消费者只可调用 IP 为 10.20.150.31 机器上的服务

当然,服务消费者匹配条件为空,表示不对消费者进行限制

服务提供者为空,表示对指定的消费者禁用服务

高频的路由配置:

白名单:

host != 10.20.30.140.50,10.20.30.140.51 =>

不是(10.20.30.140.50,10.20.30.140.51)的不可以访问

黑名单:

host != 10.20.30.140.50,10.20.30.140.51 =>

是(10.20.30.140.50,10.20.30.140.51)的不可以访问

读写分离:

method = fifind,list,get,is  => host = 172.22.3.94,172.22.3.95,172.22.3.96

是(fifind , list , get , is)的访问ip为(172.22.3.94,172.22.3.95,172.22.3.96)的服务端

method != fifind,list,get,is => host = 172.22.3.97,172.22.3.98

不是(fifind , list , get , is)的访问ip为(172.22.3.94,172.22.3.95,172.22.3.96)的服务端

前后台分离:

application =  front => host = 172.22.3.91,172.22.3.92,172.22.3.93

是(front【前端】)的访问ip为(172.22.3.91,172.22.3.92,172.22.3.93)的服务端

application != front => host = 172.22.3.94,172.22.3.95,172.22.3.96

意思:应用不是(front【前端】)的访问ip为(172.22.3.91,172.22.3.92,172.22.3.93)的服务端

ConditionRule

条件路由规则主体。定义路由规则生效的目标服务或应用、流量过滤条件以及一些特定场景下的行为。

字段名类型描述必填
configVersionstring条件路由的版本,当前版本为 v3.0
scopestring支持 serviceapplication 两种规则
keystring应用到的目标服务或应用程序的标识符 - 当 scope:service 时, key应该是该规则生效的服务名比如 org.apache.dubbo.samples.CommentService - 当 scope:application 时, then key应该是该规则应该生效的应用名称,比如说my-dubbo-service.
enabledbool规则是否生效 当 enabled:false 时,规则不生效
conditionsstring[]配置中定义的条件规则,详情可以看条件规则
forceboolT路由后实例子集为空时的行为。 true 则抛出一个No Provider Exception。 false 则忽略规则,直接去请求其他的实例。默认值是false
runtimebool是否为每个 rpc 调用运行路由规则或使用路由缓存(如果可用)。默认值是false(false则走缓存,true不走缓存)

Condition

Condition 为条件路由规则的主体,类型为一个复合结构的 string 字符串,如 method=getComment => region=Hangzhou。其中,

  • => 之前的为请求参数匹配条件,指定的 匹配条件指定的参数 将与 消费者的请求上下文 (URL)、甚至方法参数 进行对比,当消费者满足匹配条件时,对该消费者执行后面的地址子集过滤规则。

  • => 之后的为地址子集过滤条件,指定的

    过滤条件指定的参数
    

    将与

    提供者实例地址 (URL)
    

    进行对比,消费者最终只能拿到符合过滤条件的实例列表,从而确保流量只会发送到符合条件的地址子集。

    • 如果匹配条件为空,表示对所有请求生效,如:=> status != staging
    • 如果过滤条件为空,表示禁止来自相应请求的访问,如:application = product =>

匹配/过滤条件

参数支持

  • 服务调用上下文,如:interface, method, group, version 等
  • 请求上下文,如 attachments[key] = value
  • 方法参数,如 arguments[0] = tom
  • URL 本身的字段,如:protocol, host, port 等
  • URL 上任务扩展参数,如:application, organization 等
  • 支持开发者自定义扩展

条件支持

  • 等号 = 表示 “匹配”,如:method = getComment
  • 不等号 != 表示 “不匹配”,如:method != getComment

值支持

  • 以逗号 , 分隔多个值,如:host != 10.20.153.10,10.20.153.11
  • 以星号 * 结尾,表示通配,如:host != 10.20.*
  • 以美元符 $ 开头,表示引用消费者参数,如:region = $region
  • 整数值范围,如:userId = 1~100、userId = 101~
  • 支持开发者自定义扩展

3、标签路由

标签路由通过将某一个服务的实例划分到不同的分组,约束具有特定标签的流量只能在指定分组中流转,不同分组为不同的流量场景服务,从而达到实现流量隔离的目的,可以作为蓝绿发布、灰度发布等场景能力的基础。

目前有两种方式可以对实例打标,分别是动态规则打标静态规则打标动态规则打标 可以在运行时动态的圈住一组机器实例,而 静态规则打标 则需要实例重启后才能生效,其中,动态规则相较于静态规则优先级更高,而当两种规则同时存在且出现冲突时,将以动态规则为准。

标签路由是一套严格隔离的流量体系,对于同一个应用而言,一旦打了标签则这部分地址子集就被隔离出来,只有带有对应标签的请求流量可以访问这个地址子集,这部分地址不再接收没有标签或者具有不同标签的流量。

举个例子,如果我们将一个应用进行打标,打标后划分为 tag-a、tag-b、无 tag 三个地址子集,则访问这个应用的流量,要么路由到 tag-a (当请求上下文 dubbo.tag=tag-a),要么路由到 tag-b (dubbo.tag=tag-b),或者路由到无 tag 的地址子集 (dubbo.tag 未设置),不会出现混调的情况。

标签路由的作用域是提供者应用,消费者应用无需配置标签路由规则。一个提供者应用内的所有服务只能有一条分组规则,不会有服务 A 使用一条路由规则、服务 B 使用另一条路由规则的情况出现。以下条件路由示例,在 shop-detail 应用中圈出了一个隔离环境 graygray 环境包含所有带有 env=gray 标识的机器实例。

configVersion: v3.0
force: true
enabled: true
key: shop-detail
tags:
  - name: gray
    match:
      - key: env
        value:
          exact: gray

假设有一个微服务应用,包含两个版本的服务实例:v1和v2。现在我们希望通过标签路由来控制流量,将一部分流量路由到v1,另一部分流量路由到v2。

首先,在启动v1和v2的实例时,我们可以给它们分别打上静态的标签,如下:

  • v1实例:打上标签tag-a
  • v2实例:打上标签tag-b

然后,我们可以配置一个规则,使得带有特定标签的请求流量可以路由到相应的实例。这可以通过配置中心或其他方式进行配置。例如,我们定义以下规则:

  • 请求上下文中的dubbo.tag=tag-a,则将流量路由到v1实例。
  • 请求上下文中的dubbo.tag=tag-b,则将流量路由到v2实例。
  • 请求上下文中没有dubbo.tag的标签,则流量会路由到默认的地址子集。

现在,如果有100个请求,其中80个请求的dubbo.tag=tag-a,20个请求的dubbo.tag=tag-b,那么标签路由将根据标签规则将80%的流量路由到v1实例,20%的流量路由到v2实例。

通过这种方式,我们可以实现简单的蓝绿发布或灰度发布。我们可以在v1实例上进行新功能的测试和验证,同时保留v2实例作为备份或者线上版本。当我们确认新功能稳定可靠后,可以通过调整标签路由的规则,逐渐增加流量到v2实例,最终完成版本的切换。

这只是一个简单的例子,实际上,标签路由可以根据具体的需求和场景来定义更多的规则,并且可以结合权重、负载均衡等策略来更精确地控制流量的分发和管理。

TagRule

标签路由规则主体。定义路由规则生效的目标应用、标签分类规则以及一些特定场景下的行为。

FieldTypeDescriptionRequired
configVersionstringThe version of the tag rule definition, currently available version is v3.0Yes
keystringThe identifier of the target application that this rule is about to controlYes
enabledboolWhether enable this rule or not, set enabled:false to disable this rule.Yes
tagsTag[]The tag definition of this rule.Yes
forceboolThe behaviour when the instance subset is empty after routing. true means return no provider exception while false means fallback to subset without any tags.No
runtimeboolWhether run routing rule for every rpc invocation or use routing cache if available.No

Tag

标签定义,根据 match 条件筛选出一部分地址子集。

FieldTypeDescriptionRequired
namestringThe name of the tag used to match the dubbo.tag value in the request context.Yes
matchMatchConditionA set of criterion to be met for instances to be classified as member of this tag.No

MatchCondition

定义实例过滤条件,根据 Dubbo URL 地址中的特定参数进行过滤。

FieldTypeDescriptionRequired
keystringThe name of the key in the Dubbo url address.Yes
valueStringMatch (oneof)The matching condition for the value in the Dubbo url address.Yes

4、脚本路由

脚本路由为流量管理提供了最大的灵活性,所有流量在执行负载均衡选址之前,都会动态的执行一遍规则脚本,根据脚本执行的结果确定可用的地址子集。

脚本路由只对消费者生效且只支持应用粒度管理,因此, key 必须设置为消费者应用名;脚本语法支持多种,以 Dubbo Java SDK 为例,脚本语法支持 Javascript、Groovy、Kotlin 等,具体可参见每个语言实现的限制。

脚本路由由于可以动态加载远端代码执行,因此存在潜在的安全隐患,在启用脚本路由前,一定要确保脚本规则在安全沙箱内运行。

configVersion: v3.0
key: demo-provider
type: javascript
enabled: true
script: |
  (function route(invokers,invocation,context) {
      var result = new java.util.ArrayList(invokers.size());
      for (i = 0; i < invokers.size(); i ++) {
          if ("10.20.3.3".equals(invokers.get(i).getUrl().getHost())) {
              result.add(invokers.get(i));
          }
      }
      return result;
  } (invokers, invocation, context)); // 表示立即执行方法  

ScriptRule

脚本路由规则主体。定义脚本规则生效的目标消费者应用、流量过滤脚本以及一些特定场景下的行为。

FieldTypeDescriptionRequired
configVersionstringThe version of the script rule definition, currently available version is v3.0Yes
keystringThe identifier of the target application that this rule is about to apply to.Yes
typestringThe script language used to define script.Yes
enabledboolWhether enable this rule or not, set enabled:false to disable this rule.Yes
scriptstringThe script definition used to filter dubbo provider instances.Yes
forceboolThe behaviour when the instance subset is empty after after routing. true means return no provider exception while false means ignore this rule.No

Script

script 为脚本路由规则的主体,类型为一个具有符合结构的 string 字符串,具体取决于 type 指定的脚本语言。

以下是 type: javascript 的一个脚本规则示例:

(function route(invokers,invocation,context) {
      var result = new java.util.ArrayList(invokers.size());
      for (i = 0; i < invokers.size(); i ++) {
          if ("10.20.3.3".equals(invokers.get(i).getUrl().getHost())) {
              result.add(invokers.get(i));
          }
      }
      return result;
  } (invokers, invocation, context)); // 表示立即执行方法
  • 17
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值