灰度发布 Gray Release(又名金丝雀发布 Canary Release)。不停机旧版本,部署新版本,高比例流量(例如:95%)走旧版本,低比例流量(例如:5%)切换到新版本,通过监控观察无问题,逐步扩大范围,最终把所有流量都迁移到新版本上。属无损发布。
优点:灵活简单,不需要用户标记驱动。安全性高,新版本如果出现问题,只会发生在低比例的流量上
缺点:成本较高,需要部署稳定/灰度两套环境
微服务体系架构中,服务之间的依赖关系错综复杂,有时某个功能发版依赖多个服务同时升级上线。我们希望可以对这些服务的新版本同时进行小流量灰度验证,这就是微服务架构中特有的全链路灰度场景,通过构建从网关到整个后端服务的环境隔离来对多个不同版本的服务进行灰度验证。在发布过程中,我们只需部署服务的灰度版本,流量在调用链路上流转时,由流经的网关、各个中间件以及各个微服务来识别灰度流量,并动态转发至对应服务的灰度版本。
**无论是微服务网关还是微服务本身都需要识别流量,根据治理规则做出动态决策。当服务版本发生变化时,这个调用链路的转发也会实时改变。**相比于利用机器搭建的灰度环境,这种方案不仅可以节省大量的机器成本和运维人力,而且可以帮助开发者实时快速的对线上流量进行精细化的全链路控制。
全链路灰度设计思路
- 链路上各个组件和服务能够根据请求流量特征进行动态路由。
- 需要对服务下的所有节点进行分组,能够区分版本。
- 需要对流量进行灰度标识、版本标识。
- 需要识别出不同版本的灰度流量。
首先,需要支持动态路由功能,对于Spring Cloud、Dubbo开发框架,可以对出口流量实现自定义Filter,在该Filter中完成流量识别以及标签路由。同时需要借助分布式链路追踪技术完成流量标识链路传递以及流量自动染色。此外,需要引入一个中心化的流量治理平台,方便各个业务线的开发者定义自己的全链路灰度规则。实现全链路灰度的能力,无论是成本还是技术复杂度都是比较高的,以及后期的维护、扩展都是非常大的成本。
标签路由
标签路由通过对服务下所有节点按照标签名和标签值不同进行分组,使得订阅该服务节点信息的服务消费端可以**按需访问该服务的某个分组,**即所有节点的一个子集。服务消费端可以使用服务提供者节点上的任何标签信息,根据所选标签的实际含义,消费端可以将标签路由应用到更多的业务场景中。
节点打标
给服务节点添加不同的标签:
- K8S:在使用Kubernetes Service作为服务发现的业务系统中,服务提供者通过向ApiServer提交Service资源完成服务暴露,服务消费端监听与该Service资源下关联的Endpoint资源,从Endpoint资源中获取关联的业务Pod 资源,读取上面的Labels数据并作为该节点的元数据信息。所以,我们只要在业务应用描述资源Deployment中的Pod模板中为节点添加标签即可。
- Nacos:一般是需要业务根据其使用的微服务框架来决定打标方式。如果Java应用使用的Spring Cloud微服务开发框架,我们可以为业务容器添加对应的环境变量来完成标签的添加操作。比如我们希望为节点添加版本灰度标,那么为业务容器添加
spring.cloud.nacos.discovery.metadata.version=gray
,这样框架向Nacos注册该节点时会为其添加一个标签verison=gray
。
流量染色
为请求流量添加不同灰度标识来方便区分。我们可以在请求的源头上对流量进行染色,前端在发起请求时根据用户信息或者平台信息的不同对流量进行打标。如果前端无法做到,我们也可以在微服务网关上对匹配特定路由规则的请求动态添加流量标识。此外,流量在链路中流经灰度节点时,如果请求信息中不含有灰度标识,需要自动为其染色,接下来流量就可以在后续的流转过程中优先访问服务的灰度版本。保证请求链路上的各个组件能够识别出不同的灰度流量。
分布式链路追踪
借助于分布式链路追踪思想,我们也可以传递一些自定义信息,比如灰度标识。保证灰度标识能够在链路中一直传递下去。
框架
总结梳理
全链路灰度发布
标签路由、节点打标(K8S, Nacos)、流量染色、分布式链路追踪
框架:
-
Discovery(免费):网关配置权重,微服务配置版本号
-
MSE(阿里云平台)