-
Notifications
You must be signed in to change notification settings - Fork 495
服务路由之规则路由
元数据路由和就近路由本质上是基于服务实例的元数据进行筛选,是为了支持具体特定的场景而内置的服务路由能力。无需下发任何路由规则,使用起来非常简单。
而实际业务场景非常复杂,例如以下几种典型的业务场景:
- 内部员工路由到一套生产灰度环境,外部普通用户则路由到生产正式环境。(ps:灰度环境是一种特殊的生产环境,只是服务于内部员工,常用于新版本灰度)
- VIP 客户路由到一套高保环境,普通客户路由到普通环境
以上两种业务场景,则无法通过元数据路由或者就近路由实现。因为涉及到业务请求参数,而不是系统维度的环境变量。
规则路由就是用于满足复杂业务场景而实现的一套基于规则的服务路由实现。由于规则模型设计的非常灵活,所以能够满足绝大多数复杂的业务场景。简化的架构图如下图所示:
从以上介绍可知,规则路由的核心在于服务路由的规则模型,后续讲会详细讲解规则模型。
注意:
1.5.0
版本后才支持规则数据路由
请参考 服务路由基础操作 文档,引入依赖以及增加配置。
服务实例染色即服务实例启动的时候,通过某些方式获取到当前实例的元信息,并注册到注册中心时携带元信息。如何染色请参考 服务注册元数据
还是以 OrderSerivce
调用 UserService
为例,
OrderSerivce
称为主调端,而 UserSerivce
称为被调端。
这里需要理解一下,路由规则附属的实体以及实际执行路由规则的实体的定义。
路由规则附属的实体
路由规则附属的实体,指的是在界面上配置路由规则时,是在哪个服务上配置路由规则。既可以配置在主调端的 Outbound
规则上,也可以配置再被调端的 Inbound
规则上。当有规则冲突时,主调端的 Outbound
规则优先级高于 被调端的 Inbound
规则。
执行路由规则的实体
执行路由规则的实体,指的是实际运行时发起服务调用并按照路由规则路由的实体,所以执行路由规则的实体是主调端,也就是 OrderService
。
路由本质上解决的是 “哪些请求,去哪里” 的问题,所以拆解来看,模型核心是两部分,既 “哪些请求” 和 “去哪里”。
“哪些请求” 也就是流量筛选,例如:
- 来自调用方 OrderService 的请求
- 用户 id 末尾是偶数的请求
- 请求中带有某个流量标签的请求
“去哪里” 也就是流量目的地,例如:
- 满足某些条件的流量去蓝组,其它请求去绿组
- 满足某些条件的流量去高保环境分组,其它请求去普通环境分组
这部分很好理解,在界面上新建路由规则时,对应以下截图部分:
在服务调用,服务治理模型里,如何区分请求?答案是通过流量标签。标签是最高维度的抽象,所有不同的业务场景到流量治理层面都转化为标签。例如,uid
是一个标签,env
也是一个标签。
可以通过两种方式在流量链路上传递元数据标签。
方式一:起始节点 Transitive
标签
例如 SvcA
-> SvcB
-> SvcC
链路,SvcA
节点定义的 Transitive
标签,都会自动在链路上传递。例如 SvcA 定义了
`SCT_METADATA_CONTENT_ENV=dev1`
`SCT_METADATA_CONTENT_TRANSITIVE=ENV`
这样 ENV=dev1
就会在链路上传递,每个节点都可以拿到 ENV
信息。
方式二:请求 Header 中设置传递标签
很多公司都会把网关作为流量的入口,网关全局一套,这样就无法通过起始节点的环境变量来区分流量链路了。所以需要一种动态请求打标的能力,如下图所示:
网关的主调方通过在请求里增加 X-SCT-Metadata-Transitive-${key}=value
就能对流量进行动态打标。
把 Http 请求里的某些字段作为流量标签,并且只针对带有某些标签的请求进行限流。例如 Query Param
有一个 uid
字段,期望只对某些 uid
限流。
场景一:SCT 版本 < 1.8.1
,Polaris 版本 < 1.12.0
老版本的 SCT 和 Polaris 为了支持这种场景,我们定义了一套标签规则表达式,例如 ${http.query.uid}
表示请求 Query Param
里的 uid
字段,如下图所示,表示 uid=1000
的用户。
当前支持的标签规则表达式如下:
-
${http.query.xxx}
- 表示查询请求的参数
-
${http.header.xxx}
- 表示请求头里的参数
-
${http.cookie.xxx}
- 表示 cookie 里的参数
-
${http.method}
- 表示请求的方法,GET、POST、PUT 等
-
${http.uri}
- 表示请求的 Path,注意 / 开头,例如:/user
场景二:SCT < 1.8.1
,Polaris 版本 >= 1.12.0
北极星从 1.12.0
之后,支持了页面选择 Header
、Query
等参数表单,但是格式有所不同,例如 $header.user
,所以低版本的 SCT 解析不了这种格式。
SCT 1.8.1
版本之后,兼容了 $header.user
格式。所以如果您的 SCT 版本低于 1.8.1
可通过自定义标签来实现,表达式格式和上一节一致,如下图所示:
场景三:SCT 版本 >= 1.8.1
高版本的 SCT 兼容了所有格式。
在一些复杂的场景下,内置的标签表达式可能无法支持,比如请求 Body 业务对象中的某个参数等。此时可以通过实现 RouterLabelResolver SPI 来自定义从请求中获取标签。
流量目的地则非常简单,主调方通过从注册中心获取到实例信息,并且每一个实例都会有元数据信息。通过实例的元信息来划分流量目的地分组。 如下图所示:
筛选之后的流量,50%
去 env=blue
组,50% 去 env=green
组。
Spring Cloud Tencent
扩展了 Spring Boot
标准的 Actuator 能力,通过 Actuator 接口,可以实时查询当前运行实例内存里下发的路由规则,便于排查问题。详细可以参考: Actuator Endpoint 扩展
只要理解了 “哪些流量,去哪里” 并且“在服务调用,服务治理领域里最高抽象是标签” 这两个核心点,就很好理解。
以 feign 调用为例,例如调用 http://user-serivce/user/get
。
- 根据服务名(user-service)获取目标服务全量实例地址集合
- 这一步中,SCT 只会返回健康的实例集合。细节可参考源码PolarisLoadBalancer.java
- 根据元数据路由规则从全量实例中挑出部分满足规则的实例子集
- 这一步中,SCT 会执行一次地址 Filter 链,输入是全量地址,输出是经过所有地址 Filter 之后的结果。其中一个 Filter 就是规则路由 Filter RuleBasedRouter。执行 Filter 链的调用代码请参考:PolarisLoadBalancerCompositeRule#doRouter。
- RuleBasedRouter 的核心逻辑就是根据下发的路由规则去匹配流量以及根据权重挑选流量目的地。
- 根据第二步的实例子集,执行负载均衡策略,选中其中一个实例。并替换请求 Url 例如:
http://192.168.1.1:8080/user/get
- 执行负载均衡调用代码请参考:PolarisLoadBalancerCompositeRule#choose
- 您在使用过程中遇到任何问题,请提 Issue 或者加入我们的开发者群告诉我们,我们会在第一时间反馈
- Spring Cloud Tencent 社区期待您的加入,一个 Star、PR 都是对我们最大的支持
- 项目介绍
- 使用指南
- 最佳实践
- 开发文档
- 学习资料