关键字:蓝绿发布, 装饰模式,桥接模式,spring cloud
公司 saas 平台,灰度发布用于先让小量租户使用,再逐级增加用户量,降低版本变更风险,支持服务个性化,是 saas 平台关键组件。考虑到组件关键性,saas 需要定向租户发布(自定义策略),因此对框架原理源码深度分析
一. 原理分析
- 管理台/控制台 配置管理/路由增删查改管理
- 策略/框架/注册中心/负载均衡 装饰 ribbon,切入 spring cloud 框架,执行 dicovery 自身的服务路由选择逻辑;框架使用桥接模式,在不使用类继承下,实现服务中心根据灰度配置获取/过滤服务(Server)实例,负载均衡根据灰度策略选择服务实例
- 灰度发布上下文收集/传递 网关/servlet filter 收集灰度发布上下文,传递 RestTemplate/feign 拦截器
- 全链路监控 支持 opentracing,接入 skywalking
- 流量防护 集成 sentinel
- 配置中心 适配 apollo,nacos,zookeeper 等
二. 核心源码分析
分析重点
如上文所述,”蓝绿灰度发布实质是选择服务实例”,核心设计原理:
装饰负载均衡器框架,按配置规则根据服务元数据选择(apply,choose)服务实例
*apply 实例是否符合规则,若是,放在候选列表
*choose 选择(候选列表)哪个实例
1. 服务发现框架
服务发现框架通过装饰服务发现类,DiscoveryClient,NacosServerList,对获取的服务实例过滤,功能同服务路由框架,这里就不分析
2. 服务路由框架
discovery v6 只支持 ribbon,未支持 spring cloud loadbalancer
IRule ribbon 接入点, 接管负载均衡逻辑DiscoveryEnabledBaseRule/PredicateBasedRuleDecorator 负载均衡装饰,使用权重随机策略选择(chose)Server 实例;
DiscoveryEnabledBasePredicate 决定是否应用(apply)Server 实例,桥接到 adapter 组件,执行自身 apply 服务实例逻辑,即根据灰度规则及服务元素据决定是否应用该实例
DefaultDiscoveryEnabledStrategy 继承该类实现自定义路由策略
灰度发布上下文收集和传递
微服务架构下,服务间调用发生在不同节点,每个服务调用下一个服务需要根据灰度配置选择下一个服务实例,因此需要机制透明传递灰度上下文
3.1 灰度标签初始收集
框架使用过滤器(StrategyRoute Filter)初始收集灰度上下文,有 zuul/servlet/gateway 等多种实现,原理相同,收集后放入请求 header,后续传递支持 feign/resttemplate 等
AbstractXXXStrategyRouteFilter 负责 header 设置逻辑,zuul 置入RequestContext,servlet 环境置入到 HttpRequest
StrategyContextHolder 负责获取灰度配置,如版本,区域,权重等
两者使用模板模式,逻辑放到抽象类,分离不同实现到具体类,如,getHeader
3.2 feign/RestTemplate 灰度标签传递
feign/RestTemplate 使用自身拦截器机制,接力传递灰度标签上下文
参看 FeignStrategyInterceptor/RestTemplateStrategyInterceptor
二. 自定义策略-saas定向租户发布
多租户定向发布分组策略,支持多个发布分组,每个分组独立设置定向租户
实现支持多服务发布分组,每个分组可独立配置定向租户
同时,实现支持租户定制服务,即,一些用户使用A服务1.0,另一些用户使用A服务2.0
> 服务分组发布策略,继承DefaultDiscoveryEnabledStrategy,接管ribbon的apply方法,决定是否应用服务实例,策略支持多个服务发布
> 服务发布,互相不重叠的一组发布服务,每个服务发布配置SeviceFeatureMatcher,SeviceFeatureMatcher是判断是否应用服务实例的逻辑,判断的依据是服务bean和发布规则
> 服务bean,包括服务Id,服务特性,如,版本,所属分组等
自定义实现源码(收费),包括策略实现,demo