就近路由
功能描述
北极星提供基于 地域(region) - 城市(zone) - 园区(campus) 这3元组组成的地域信息进行就近路由的能力,能够根据主调的地域信息,结合被调实例的地域信息,进行匹配。实例本身的地域信息来源于有以下几个途径
polaris服务端的 CMDB 插件
- 提供 CMDB 对接的插件,用户可以根据 polaris服务端 中 CMDB 的插件定义,对接自己的 CMDB 系统。当 polaris 客户端通过ReportClient接口上报信息至polaris服务端,然后由服务端的 CMDB 插件填充当前客户端所在地理位置信息并通知给客户端
polaris客户端的 CMDB 插件
- 提供 CMDB 插件,用户可以根据 polaris客户端 中对于 CMDB 插件的定义,根据客户端所在环境的特性来实现不同的本地地址位置信息获取插件
- env: 将地理位置信息注入至客户端所在机器的环境中,客户端就可以基于系统环境变量自动获取地理位置信息
- qcloud: 可以根据用户所部署的云环境,根据该云厂商提供的环境信息获取接口,自动获取地址位置信息,当前已实现基于 Tencent Cloud的客户端地址插件
配置设计
SDK配置
Spring Cloud Tencent 使用
SCT(Spring Cloud Tencent 的缩写) 内置了一组位置元数据环境变量标签, 服务在启动时,SCT 会读取这一组环境变量作为元数据上报到注册中心,从而传递到主调端。
export SCT_METADATA_CAMPUS=ap-guangzhou-1
export SCT_METADATA_ZONE=ap-guangzhou
export SCT_METADATA_REGION=china
可以通过查看启动日志确认是否正确打标:
grep "Loaded static metadata info" xx.log
相关文档
polaris-go 客户端使用
SDK配置属于客户端全局配置,基于该SDK实例所发起的服务发现,都遵循该就近路由策略。 由于就近路由能力通过SDK服务路由模块的插件进行提供,因此就近路由相关配置,也作为插件的特有配置来进行提供。
global:
location:
# 设置 polaris-go 进程地理信息的提供插件
# 设置为 env 时,可以在 linux 中注入以下环境变量
# POLARIS_INSTANCE_REGION: 设置 region 信息, 例如 china
# POLARIS_INSTANCE_ZONE: 设置 zone 信息, 例如 ap-guangzhou
# POLARIS_INSTANCE_CAMPUS: 设置 IDC 信息, 例如 ap-guangzhou-3
provider: env
consumer:
serviceRouter:
# 服务路由链
chain:
- nearbyBasedRouter
# 插件特定配置
plugin:
nearbyBasedRouter:
# 默认就近区域:默认城市
matchLevel: zone
# 最大就近区域,默认为空(全匹配)
maxMatchLevel: zone
服务配置
- 在控制台上通过可视化的方式操作开关就近路由。
- polaris服务端下发服务数据时,在服务元数据中加入internal-enable-nearby=true|false的元数据,SDK通过服务元数据解析出服务是否开启就近路由。
就近流程
初始化
- 用户调用NewConsumerAPI或者NewProviderAPI后
- SDK 会使用客户端节点的 IP,往 Polaris 服务端查询该 IP 对应的 CMDB 信息,查询后的结果后返回给客户端
- 如果查询的结果中,没有携带地址信息,则客户端会走自己本地的 CMDB 插件查询客户端的地理位置信息
地域匹配
服务调用过程中,使用拉取的客户端地域信息,进行全词匹配。匹配规则如下:
- 优先按照 matchLevel 进行匹配,匹配不成功(实例不存在或者可用实例比例少于阈值),则进行降级
- 就近降级按照 degrade 所配置的策略进行降级,会进行逐级的降级匹配,直到 lowestMatchLevel
就近场景
按照不同的场景,就近路由对被调服务的过滤策略如下表所示:
降级策略:
降级策略:服务实例不可用 | 降级策略:服务实例不存在 | |
---|---|---|
matchLevel区域不存在实例 | 逐级降级直到maxMatchLevel。若实例全部不存在,返回LocationMismatch错误 | 逐级降级直到maxMatchLevel,若都不存在,返回LocationMismatch错误 |
matchLevel区域存在实例,区域中不可用实例百分比大于等于降级比例 | 返回matchLevel区域实例 | 逐级降级直到maxMatchLevel,若都不满足健康实例返回条件,返回实例数大于0的最小区域实例 |
被调信息异常策略
maxMatchLevel != “” | maxMatchLevel == “” | |
---|---|---|
被调实例对应的CMDB字段缺失 | 忽略该实例 | 当降级到最高匹配级别(全匹配)时,会返回这部分服务实例 |
跨机房容灾场景
背景
服务端有广州云、深圳、南京云设备。客户端在深圳。 那么深圳客户端访问这个服务端时,返回实例列表由深圳、广州、南京实例组成,同时设置优先级,让深圳客户端优先访问深圳;然后是广州(同可用区);最后是南京
解决方案
假设存在服务A,服务A下面节点存在分别属于深圳、广州、南京的实例,CMDB信息如下:
- 华南/ap-guangzho/ap-guangzhou-3
- 华南/ap-shenzhen/ap-shenzhen-2
- 华东/ap-nanjing/ap-nanjing-4
客户端配置:
consumer:
serviceRouter:
plugin:
nearbyBasedRouter:
# 默认按zone进行就近
matchLevel: zone
就近逻辑
客户端配置 matchLevel: zone,默认只访问同 zone(深圳) 的实例,当深圳可用区无实例后,降级访问 region(华南) 的 实例(可访问广州的实例),当华南地区实例也达到降级条件后,降级访问全部 region(包含华东-南京) 的实例