Dubbo 路由机制是在服务间的调用时,通过将服务提供者按照设定的路由规则来决定调用哪一个具体的服务。
路由服务结构
Dubbo 实现路由都是通过实现 RouterFactory 接口。当前版本 dubbo-2.7.5 实现该接口类如下:
路由实现工厂类是在 router 包下
由于 RouterFactory 是 SPI 接口,同时在获取路由 RouterFactory#getRouter 方法上有 @Adaptive(“protocol”) 注解,所以在获取路由的时候会动态调用需要的工厂类。
可以看到 getRouter 方法返回的是一个 Router 接口,该接口信息如下
其中 Router#route 是服务路由的入口,对于不同类型的路由工厂,有特定的 Router 实现类。
以上就是通过解析 URL,获取到具体的 Router,通过调用 Router#router 过滤出符合当前路由规则的 invokers。
服务路由实现
上面展示了路由实现类,这几个实现类型中,ConditionRouter 条件路由是最为常用的类型,由于文章篇幅有限,本文就不对全部的路由类型逐一分析,只对条件路由进行具体分析,只要弄懂这一个类型,其它类型的解析就能容易掌握。
条件路由参数规则
在分析条件路由前,先了解条件路由的参数配置,官方文档如下:
条件路由规则内容如下:
条件路由实现分析
分析路由实现,主要分析工厂类的 xxxRouterFactory#getRouter 和 xxxRouter#route 方法。
ConditionRouterFactory#getRouter
ConditionRouterFactory 中通过创建 ConditionRouter 对象来初始化解析相关参数配置。
在 ConditionRouter 构造函数中,从 URL 里获取 rule 的字符串格式的规则,解析规则在 ConditionRouter#init 初始化方法中。
1 | public void init(String rule) { |
以路由规则字符串中的=>
为分隔符,将消费者匹配条件和提供者匹配条件分割,解析两个路由规则后,赋值给当前对象的变量。
调用 parseRule 方法来解析消费者和服务者路由规则。
1 | // 正则验证路由规则 |
上面就是解析条件路由规则的过程,条件变量的值都保存在 MatchPair 中的 matches、mismatches 属性中,=
和,
的条件变量值放在可以匹配的 matches 中,!=
的条件变量值放在不可匹配路由规则的 mismatches 中。赋值过程中,代码还是比较优雅。
实际上 matches、mismatches 就是保存的是条件变量值。
ConditionRouter#route
Router#route
的作用就是匹配出符合路由规则的 Invoker 集合。
1 | // 在初始化中进行被复制的变量 |
上面代码可以看到,只要消费者没有匹配的规则或提供者没有匹配的规则及 force=false 时,不会返回传入的参数的 Invoker。
匹配消费者路由规则和提供者路由规则方法是 matchWhen 和 matchThen
这两个匹配方法都是调用同一个方法 matchCondition 实现的。将消费者或提供者 URL 转为 Map,然后与 whenCondition 或 thenCondition 进行匹配。
匹配过程中,如果 key (即 sampleValue 值)存在对应的值,则通过 MatchPair#isMatch 方法再进行匹配。
1 | private boolean isMatch(String value, URL param) { |
匹配过程再调用 UrlUtils#isMatchGlobPattern 实现
1 | public static boolean isMatchGlobPattern(String pattern, String value, URL param) { |
就这样完成全部的条件路由规则匹配,虽然看似代码较为繁杂,但是理清规则、思路,一步一步还是较好解析,前提是要熟悉相关参数的用法及形式,不然代码较难理解。
最后
单纯从逻辑上,如果能够掌握条件路由的实现,去研究其它方式的路由实现,相信不会有太大问题。只是例如像脚本路由的实现,你得先会使用脚本执行引擎为前提,不然就不理解它的代码。最后,在 dubbo-admin 上可以设置路由,大家可以尝试各种使用规则,通过实操才能更好掌握和理解路由机制的实现。