文章目录
0、分布式系统灰度要实现的功能清单
1.1、灰度因子可全链路传递
-
后端/前端往cookie里携带灰度因子
-
浏览器端发起时自动携带
-
后端分布式节点间自动透传
1.2、前端资源灰度
- 非灰度/灰度前端资源目录区分存放
- 前端请求灰度路由
1.3、Rest API请求灰度
- 非灰度/灰度web并存运行
- 前端请求灰度路由
1.4、分布式RPC(Dubbo)调用灰度
隔离性
- 灰度应用的Dubbo服务API,不被环境里其他非灰度应用所调用
- 灰度应用的Dubbo服务API,可被环境里上游灰度应用所调用
- 灰度应用调用下游其他Dubbo服务APIs时,按灰度规则进行非灰度/灰度的调用
1.5、MQ生产/消费灰度
隔离性
- 灰度应用产生的MQ,只被下游灰度应用消费
- 非灰度应用产生的MQ,只被下游非灰度应用消费
1.6、数据库灰度
一致性
- 灰度应用对应DB数据的相对(非灰度应用)一致性。
- [按需]灰度关闭时的(相对非灰度DB的)数据持久性
- TBD
1、携带灰度因子
1.1、Http请求中
携带位置:
- Cookie
一般是以下几种灰度因子可参考:
- Client IP:Http请求自动携带
- 业务编码:
- 【方式一】向登录模块提需求,在登录时往cookie里携带你需要的灰度因子(笔者的场景:租户Code)
- 【方式二】在前置版本中,让前端在发起请求时,将业务编码塞在cookie中。针对前台可匿名访问的页面。
- (按流量比例:2C会用。2B因参与角色的多样性,不适用单按流量比例)
1.2、JVM中
-
在JVM启动参数上带上自定义标识:useGreyMode
-
java -DuseGreyMode=1
-
-
在运行期代码中,读取此标识是否为True
-
public Boolean isGreyMode(){ String useGreyMode = System.getProperty("useGreyMode", "0"); if("1".equals(useGreyMode)){ //灰度模式 return Boolean.TRUE; } return Boolean.FALSE; }
-
1.3、调用链中
- 在Web层,从Http报文中解析得到灰度因子,例如:租户Code、IP
- 将租户Code、IP放入ThreadLocal进行调用链上的透传
- 在RPC层面,自动将ThreadLocal中的Code、IP放入RPC报文的指定位置,并由RPC的接收方进行解析,同样再次放入下游调用链的ThreadLocal中。
- 注意点:ThreadLocal使用TransmittableThreadLocal(https://github.com/alibaba/transmittable-thread-local)
- 为什么?在RPC和框架层面往往会有线程池模型,而常规的ThreadLocal在跨线程时就会值丢失。目前市面上只有TransmittableThreadLocal是支持线程池级别的ThreadLocal传递的。
2、前端资源灰度
要点:
- 非灰度/灰度前端资源目录区分存放
- 前端请求按灰度规则路由
- 灰度规则可动态下发生效
2.1、方案一:基于verynginx
为什么verynginx?
- 【为什么多一层】在nginx之下,再加一个本业务专用的verynginx,与其他业务的转发规则分离,可将转发规则的影响控制到本业务。
- 【为什么选verynginx】verynginx 内部是基于OpenResty,而OpenResty = nginx + lua 的框架。即nginx能做的转发和静态资源路由,verynginx都支持。而且,verynginx对配置更友好:界面化、json化、支持被动(不用轮询去查)变更生效,整体上对于灰度控制的场景使用更简单。
- https://github.com/alexazhou/VeryNginx
verynginx的配置动态生效方式:
config.json配置示例:
- 注:这里会遇到一个开发点
- 自研的灰度管理控制台中的“灰度规则”,是一种数据配置结构。
- verynginx中config.json,又是一种数据配置结构。
- 最终,是要将灰度管理控制台的具体规则,体现到verynginx中的配置文件中去。
- 在这里,有通过python实现一个转换写入工具。<