服务目录在刷新Invoker列表的过程中,会通过Router进行服务路由,筛选出符合路由规则的服务提供者。
服务路由包含一条路由规则,路由规则决定了服务消费者可以调用哪些服务提供者。
Dubbo目前提供了三种服务路由实现 - 条件路由(ConditionRouter)、脚本路由(ScriptRouter)、标签路由(TagRouter)。
可以在服务治理控制台 Dubbo-Admin 写入路由规则
应用粒度
# app1的消费者只能消费所有端口为20880的服务实例
# app2的消费者只能消费所有端口为20881的服务实例
scope: application
key: governance-conditionrouter-consumer
enabled: true
force: true
runtine: true
conditions:
- application=app1 => address=*:20880
- application=app2 => address=*:20881
服务粒度
# DemoService的sayHello方法只能消费所有端口为20880的服务实例
# DemoService的sayHi方法只能消费所有端口为20881的服务实例
scope: service
key: org.apache.dubbo.samples.goverance.api.DemoService
enabled: true
force: true
runtime: true
conditions:
- method=sayHello => address=*:20880
- method=sayHi => address=*:20881
scope
:表示路由规则的作用粒度,scope的取值会决定key的取值。必填。
key
:明确规则体作用在哪个应用或者规则。必填。
[{group}:]{service}[:{version}]
的组合。conditions
:定义具体的路由规则内容。必填。
enabled
:当前路由规则是否生效,缺省生效。
force
:当路由结果为空时,是否强制执行,如果不强制执行,路由结果为空的路由规则将自动失效,缺省为 false。
runtime
:是否在每次调用时执行路由规则,否则只在提供者地址列表变更时预先执行并缓存结果,调用时直接从缓存中获取路由结果。如果用了参数路由,必须设置为true,需要注意设置会影响调用的性能。缺省为false。
priority
:路由规则的优先级,用于排序,优先级越大越靠前执行。缺省为0。
Conditions规则体
1、格式
=>
之前的为消费者匹配条件,所有参数和消费者的URL进行对比,当消费者满足匹配条件时,对该消费者执行后面的过滤规则。
=>
之后的为提供者地址列表的过滤条件,所有参数和提供者的URL进行对比,消费者最终只拿到过滤后的地址列表。
如果匹配条件为空,表示对所有消费者应用,比如:=> host != 10.20.153.11
如果过滤条件为空,表示禁止访问,比如:host = 10.20.153.10 =>
2、表达式
参数支持
条件支持
=
表示匹配,比如 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、示例
排除预发布机
=> host != 172.22.3.91
白名单(一个服务只能有一个白名单规则,否则两条规则交叉,都被筛选掉了)
register.ip != 10.20.153.10,10.20.153.11 =>
黑名单
register.ip = 10.20.153.10,10.20.153.11 =>
提供者与消费者部署在同集群内,本机只访问本机的服务:
=> host = $host
隔离不同机房网段
host != 172.22.3.* => host != 172.22.3.*
前后台分离
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
读写分离
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
为重要应用提供额外的机器
application != kylin => host != 172.22.3.95,172.22.3.96
服务寄宿在应用上,只暴露一部分的机器,防止整个集群挂掉
=> host = 172.22.3.1*,172.22.3.2*
以下是条件路由的源码分析过程
@Override
public <T> List<Invoker<T>> route(List<Invoker<T>> invokers, URL url, Invocation invocation)
throws RpcException {
if (!enabled) {
return invokers;
}
if (CollectionUtils.isEmpty(invokers)) {
return invokers;
}
try {
// 先对服务消费者条件进行匹配,如果匹配失败,表明服务消费者 url 不符合匹配规则,
// 无需进行后续匹配,直接返回 Invoker 列表即可
if (!matchWhen(url, invocation)) {
return invokers;
}
List<Invoker<T>> result = new ArrayList<Invoker<T>>();
// 服务提供者匹配条件未配置,表明对指定的服务消费者禁用服务,也就是服务消费者在黑名单中
if (thenCondition == null) {
logger.