当服务有新版本要发布上线时,通过引流一小部分流量到新版本,可以及时发现程序问题,有效阻止大面积故障的发生。业界上已经有比较成熟的服务发布策略,比如蓝绿发布、A/B 测试以及金丝雀发布,这些发布策略主要专注于如何对单个服务进行发布。在微服务体系架构中,服务之间的依赖关系错综复杂,有时某个功能发版依赖多个服务同时升级上线。我们希望可以对这些服务的新版本同时进行小流量灰度验证,这就是微服务架构中特有的全链路灰度场景,通过构建从网关到整个后端服务的环境隔离来对多个不同版本的服务进行灰度验证。
本文将会揭开全链路灰度的神秘面纱,深入剖析全链路灰度技术内幕,引出两种不同的实现方案,并对实现方案的技术细节进行深入探讨,最后通过实践环节来展示全链路灰度在实际业务中的使用场景。
微服务架构带来的挑战
为了满足业务的迭代速度,开发者开始对原来的单体架构进行细粒度的拆分,将单体应用中的服务模块拆分成一个个独立部署运行的微服务,并且这些微服务的生命周期由对应的业务团队独自负责,有效的解决了单体架构中存在的敏捷性不足、灵活性不强的问题。常见的做法是根据业务域或者功能域进行服务拆分,如下图:
其中,流量网关是四层代理,主要功能有负载均衡、TLS 卸载以及一些安全防护功能;微服务网关是七层代理,主要用来暴露后端服务、流量治理、访问控制和流量监控。以"高内聚、低耦合"作为设计理念的微服务架构为开发者带来了前所未有的开发体验,每个业务团队专注于自身业务的代码逻辑,并通过 API 形式对外发布。服务依赖方只需引入服务提供方的 API 定义,即可完成服务之间通信,无需关心服务提供方的部署形态和内部实现。
但任何架构都不是银弹,在解决旧问题同时势必会引入一些新的问题。微服务体系中最令人头疼的问题,是如何对众多微服务进行高效、便捷的治理,主要表现在可见性、连接性和安全性这三个方面。进一步细化,微服务架构带来了以下的挑战:
本文的重点主要关注服务发布这一子领域,如何保证微服务体系中服务新版本升级过程中平滑无损,以及如何低成本的为多个微服务构建流量隔离环境,方便开发者同时对多个服务新版本进行充分的灰度验证,避免故障的发生。
什么是全链路灰度
单体架构下的服务发布
首先,我们先看一下在单体架构中,如何对应用中某个服务模块进行新版本发布。如下图,应用中的 Cart 服务模块有新版本迭代:
由于 Cart 服务是应用的一部分,所以新版本上线时需要对整个应用进行编译、打包以及部署。服务级别发布问题变成了应用级别的发布问题,我们需要对应用的新版本而不是服务来实施有效的发布策略。
目前,业界已经有非常成熟的服务发布方案,例如蓝绿发布和灰度发布。蓝绿发布需要对服务的新版本进行冗余部署,一般新版本的机器规格和数量与旧版本保持一致,相当于该服务有两套完全相同的部署环境,只不过此时只有旧版本在对外提供服务,新版本作为热备。当服务进行版本升级时,我们只需将流量全部切换到新版本即可,旧版本作为热备。我们的例子使用蓝绿发布的示意图如下,流量切换基于四层代理的流量网关即可完成。
在蓝绿发布中,由于存在流量整体切换,所以需要按照原服务占用的机器规模为新版本克隆一套环境,相当于要求原来1倍的机器资源。灰度发布的核心思想是根据请求内容或者请求流量的比例将线上流量的一小部分转发至新版本,待灰度验证通过后,逐步调大新版本的请求流量,是一种循序渐进的发布方式。我们的例子使用灰度发布的示意图如下,基于内容或比例的流量控制需要借助于一个七层代理的微服务网关来完成。
其中,Traffic Routing 是基于内容的灰度方式,比如请求中含有头部 stag=gray 的流量路由到应用 v2 版本;Traffic Shifting 是基于比例的灰度方式,以无差别的方式对线上流量按比重进行分流。相比蓝绿发布,灰度发布在机器资源成本以及流量控制能力上更胜一筹,但缺点就是发布周期过长,对运维基础设施要求较高。
微服务架构下的服务发布
在分布式微服务架构中,应用中被拆分出来的子服务都是独立部署、运行和迭代的。单个服务新版本上线时,我们再也不需要对应用整体进行发版,只需关注每个微服务自身的发布流程即可,如下:
为了验证服务 Cart 的新版本,流量在整个调用链路上能够通过某种方式有选择的路由到 Cart 的灰度版本,这属于微服务治理领域中流量治理问题。常见的治理策略包括基于 Provider 和基于 Consumer 的方式。
- 基于 Provider 的治理策略。配置 Cart 的流量流入规则,User 路由到 Cart 时使用 Cart 的流量流入规则。
- 基于 Consumer 的治理策略。配置 User 的流量流出规则, User 路由到 Cart 时使用 User 的流量流出规则。
此外,使用这些治理策略时可以结合上面介绍的蓝绿发布和灰度发布方案来实施真正的服务级别的版本发布。
全链路灰度
继续考虑上面微服务体系中对服务 Cart 进行发布的场景,如果此时服务 Order 也需要发布新版本,由于本次新功能涉及到服务 Cart 和 Order 的共同变动,所以要求在灰度验证时能够使得灰度流量同时经过服务 Cart 和 Order 的灰度版本。如下图:
按照上一小节提出的两种治理策略,我们需要额外配置服务 Order 的治理规则,确保来自灰度环境的服务 Cart 的流量转发至服务 Order 的灰度版本。这样的做法看似符合正常的操作逻辑,但在真实业务场景中,业务的微服务规模和数量远超我们的例子,其中一条请求链路可能经过数十个微服务,新功能发布时也可能会涉及到多个微服务同时变更,并且业务的服务之间依赖错综复杂,频繁的服务发布、以及服务多版本并行开发导致流量治理规则日益膨胀,给整个系统的维护性和稳定性带来了不利因素。
对于以上的问题,开发者结合实际业务场景和生产实践经验,提出了一种端到端的灰度发布方案,即全链路灰度。全链路灰度治理策略主要专注于整个调用链,它不关心链路上经过具体哪些微服务,流量控制视角从服务转移至请求链路上,仅