背景
为了保证线上业务质量,需要一套后台灰度系统。目标是通过简易的配置即可将系统中部分的用户进行灰度
需要支持的功能点
整个应用完全灰度
应用中的指定Service进行灰度
可以实现多个独立的灰度环境
修复灰度配置后可以自动更新不用重启(非必须)
Api => Service A => Service B => Service C => Service D
web-api暂时不加入灰度,如果加入灰度依赖于网关接入
如何实现?
灰度环境(gray_evn):
Id
name: 环境名
group: dubbo provider的group
status: 开启=>灰度生效 关闭=>灰度无效
hosts: 灰度服务器的ip 多个服务ip用分号分隔
remark: 备注
灰度用户表(gray_user)
Id
envId: 灰度环境
userId: 用户
灰度应用表(gray_application)
Id
envId: 灰度环境
application: 灰度的应用
model: 实现的模式 整个应用加入灰度(AllGray)或部分服务灰度(PartGray)
灰度的服务表(gray_service)
Id
applicationId: 灰度应用的Id
service: 服务的全路径
同一个灰度的服务只能出现在一个灰度的环境里
划分灰度环境
在应用启动时,根据该应用所在灰度环境机器列表,判断该应用在这个台机器是否需要灰度,如果是,再根据灰度的服务表配置服务的灰度配置(该服务设置为灰度group)。 通过使用eanPostProcessor接口来完成灰度的初始化之后,通过group把dubbo服务被划分灰度环境、正式环境。这里需要注意的是,该灰度系统的核心之一就是通过group进行灰度环境的划分。
具体流程如图:
动态的路由
dubbo服务调用的顺序:loadBalance -> filter
SpringMvc Intercepter:
1.获取当前登录用户
2.查询用户是否在哪些灰度环境中
3.把所有灰度环境的group放入到dubbo的attachment里面
GrayLoadBalance:
由于服务启动是默认是吧消费端的group设置成了“*”,所以在loadBalance里面会拿到所有Provider提供的Invoker(包括正式环境和灰度环境),把所有的Invoker通过URL中的group进行分组,在取出attachment中的groups;
判断出这次调用是走灰度还是正式;如果是灰度,需要设置一下group为灰度环境的;返回对应的Invoker
GrayFilter:
把attachment中的group的值,如果是“*”,那么设置为空