负载均衡算法是为了解决服务消费者如何从众多可用服务节点中选取一个最合适的节点发起调用。
但在业务中经常还会遇到这样的场景,比如服务A部署在北京、上海、广州三个数据中心,所有的服务节点按照所在的数据中心被分成了三组,那么服务A的消费者在发起调用时,该如何选择呢?
这就是服务路由。
什么是服务路由
服务消费者在发起服务调用时,必须根据特定规则选择服务节点,从而满足某些特定需求。
应用场景
分组调用
为了保证服务高可用,实现异地多活,一个服务往往不止部署在一个数据中心,而且出于节省成本等考虑,有些业务可能不仅在私有机房部署,还会采用公有云部署,甚至采用多家公有云部署。服务节点也会按照不同的数据中心分成不同的分组,这时对于服务消费者来说,选择哪一个分组调用,就必须有相应的路由规则。
灰度发布
在服务上线发布的过程中,一般需要先在一小部分规模的服务节点上先发布服务,然后验证功能是否正常。如果正常的话就继续扩大发布范围;如果不正常的话,就需要排查问题,解决问题后继续发布。
流量切换
在业务线上运行过程中,经常会遇到一些不可抗因素导致业务故障,比如
- 某机房光缆被挖断
- 着火等事故
导致整个机房的服务都不可用。这时就需要按照某个指令,能够把原来调用这个机房服务的流量切换到其他正常的机房。
读写分离
大多业务来说都是读多写少,服务部署时,可以把读写分开部署,所有写接口可以部署在一起,而读接口部署在另外节点。
服务路由规则
条件路由
基于条件表达式的路由规则,以下面的条件路由为例,我来给你详细讲解下它的用法。
condition://0.0.0.0/dubbo.test.interfaces.TestService? category=routers&dynamic=true&priority=2&enabled=true&rule= " + URL.encode(" host = 10.20.153.10=> host = 10.20.153.11")
condition:// 代表这是一段用条件表达式编写的路由规则,具体的规则是
host = 10.20.153.10 => host = 10.20.153.11
=>前是服务消费者的匹配条件,后面是服务提供者的过滤条件:
当服务消费者节点满足匹配条件,就对该服务消费者执行后面的过滤规则。
这段表达式表达的意义就是IP为“10.20.153.10”的服务消费者都调用IP为“10.20.153.11”的服务提供者节点。
若服务消费者的匹配条件为空,就表示对所有的服务消费者应用,就像下面的表达式一样。
=> host != 10.20.153.11
若服务提供者的过滤条件为空,就表示禁止服务消费者访问:
host = 10.20.153.10=>
具体应用场景
排除某服务节点
=> host != 172.22.3.91
一旦这条路由规则被应用到线上,所有的服务消费者都不会访问IP为172.22.3.91的服务节点,这种路由规则一般应用在线上流量排除预发布机以及摘除某个故障节点。
白名单
host != 10.20.153.10,10.20.153.11 =>
除了IP为10.20.153.10和10.20.153.11的服务消费者可以发起服务调用以外,其他服务消费者都不可以。
host = 172.22.3.* => host = 172.22.3.*
比如某个后台服务只允许特定的几台机器才可以访问,这样的话可以机器控制访问权限。
黑名单
host = 10.20.153.10,10.20.153.11 =>
除了IP为10.20.153.10和10.20.153.11的服务消费者不能发起服务调用以外,其他服务消费者都可以。
比如线上经常会遇到某些调用方不管是出于有意还是无意的不合理调用,影响了服务的稳定性,这时候可以通过黑名单功能暂时予以封杀。
机房隔离
host = 172.22.3.* => host = 172.22.3.*
IP网段为172.22.3.*的服务消费者,才可以访问同网段的服务节点。
一般应用于服务部署在多个IDC,理论上同一个IDC内的调用性能要比跨IDC调用性能要好,应用这个规则是为了实现同IDC就近访问。
读写分离
method = find*,list*,get*,is* => host =172.22.3.94,172.22.3.95 method != find*,list*,get*,is* => host = 172.22.3.97,172.22.3.98
find*、get*、is*等读方法调用IP为172.22.3.94和172.22.3.95的节点,除此以外的写方法调用IP为172.22.3.97和172.22.3.98的节点。
大部分业务读请求远大于写请求,而写请求的重要性往往要远远高于读请求,所以需要