一种dubbo逻辑路由方案(服务化隔离环境)

背景介绍

如今不少的公司都在用dubbo、springcloud作为服务化/微服务的开发框架,服务化以后应用愈来愈多,链路愈来愈长,服务环境的治理变的很困难。好比:研发团队的人不少的,同时有几个分支在开发和测试,会形成多个同名的服务存在,为了不不一样feature之间的服务不串调,不少研发人员会改服务的版本号来避免这种状况;还有一种状况是由于修改服务版本号,调用链链路上全部的节点都须要修改,存在浪费机器资源的现象。javascript

需求场景描述

  1. 稳定的测试环境通常是有测试的同窗维护的,上面的代码通常是验证完成(即将上线)的分支,或者就是和线上代码保持一致的分支(基准代码);
  2. 下图中需求1是正在开发的某个需求,它涉及了2个须要改动的应用A和B,因为他们在需求1里(代码也切分支),咱们称需求1里面的应用A为A1,需求1里面的应用B为B1;
  3. 同理,需求2也是正在开发的某个需求,由于它和需求1同时开发,涉及的应用也有重合,因此称为并发需求。需求2中的应用A为A2,应用B为B2,应用E为E2;
  4. 在不修改服务版本号的状况下,需求1的研发人员但愿A1直接调用下游B,而后B调用C1,由于应用B、C、D在需求1里面是没有代码变动的,因此完整的调用链路以下:A1->B->C1->D->E
  5. 需求2中有代码变动的应用是A二、B二、E2,不须要更变的是C、D,因此完成的调用链路以下:A2->B2->C->D->E2

总结起来:
研发只但愿调用本需求内应用,若是链路中某个应用没有代码变动,则调用稳定环境中的应用(保证链路能走通,而且把这种逻辑路由的关系传递到下游应用中)java

谈dubbo路由

dubbo框架内部自带路由的,它支持2种路由规则:ConditionRouter、ScriptRouter,MockInvokersSelector暂时不讨论。git

一、 其中ConditionRouter表示条件路由,条件表达式以 => 分割为whenRule和thenRule:

例子:*github

condition://0.0.0.0/com.foo.BarService?category=routers&dynamic=false&rule=" + URL.encode("host = 10.20.153.10 => host = 10.20.153.11"spring

  • 从url根据RULE_KEY获取路由条件路由内容
  • rule.indexOf("=>") 分割路由内容: =>前面是消费者条件(when),=>后面是provider的条件(then)
  • 分别调用parseRule(rule) 解析路由为whenRule和thenRules

ConditionRouter执行route方法:

  • 若是url不知足when条件即过来条件, 不过滤返回全部invokers
  • 遍历全部invokers判断是否知足then条件, 将知足条件的加入集合result
  • Result不为空,有知足条件的invokers返回
  • Result为空, 没有知足条件的invokers, 判断参数FORCE_KEY是否强制过来,若是强制过滤返回空, 不是返回全部即不过滤

ConditionRouter的点评

ConditionRouter并非适合咱们的需求,由于咱们须要是配合简单运维实现自动路由,不须要开发人员写额外代码和配置,很显然ConditionRouter=>后面的then条件是固定的一个provider或者一组provider,而不能动态路由;第二点是ConditionRouter在稳定测试环境的应用上也须要在URL里面打上路由标识,这就违反了咱们初衷:不须要开发人员写额外代码和配置ruby

二、 ScriptRouter表示脚本路由

经过url的RULE_KEY参数获取脚本内容,而后经过java的脚本引擎执行脚本代码, dubbo的测试用例都是经过javascript做为脚本可是理论上也支持groovy, jruby脚本并发

  • 从url获取脚本类型javascript, groovy等等
  • 从url根据RULE_KEY获取路由规则内容
  • 根据脚本类型获取java支持的脚本执行引擎

ScriptRouter的点评

ScriptRouter虽然比ConditionRouter灵活,能够在消费端执行脚原本控制路由的逻辑,可是仍是有一样的问题,对于稳定的测试环境里的应用也须要配置路由脚本,不能作到真正的少配置、少运维、少写额外代码框架

逻辑路由的方案

咱们分析了场景和需求,又分析现有的dubbo路由方案的不知足,如今来来看一下一种可行的方案:运维

  1. 逻辑路由provider和consumer都经过URL来获取路由标识
  2. 最小运维开支:经过申请应用环境的时候,在机器打上环境变量
  3. 最小的dubbo框架改动:在LoadBalance和AbstractClusterInvoker上修改逻辑路由方案

show me code

具体实现的代码,我放在github上,变动也不大,分支ide

  1. 在LoadBalance和AbstractClusterInvoker上修改逻辑路由主要逻辑
  2. 在provider注册服务的URL时,加上逻辑路由的标识
  3. dubbox新增长了一个依赖:logical-router,这是我本身写的小的jar包,方便以后作扩展(好比rest入口的应用程序,自启动的应用程序等等)
  4. 运维相关:只须要给申请相同的逻辑路由标识应用的机器,打上相同的环境变量:LOGICAL_ROUTER_ENV

diff文件

更方便的查看变动:diff文件

相关文章
相关标签/搜索