技术硬实力“我是如何理解全链路灰度的?”

2022-09-23 18:04:30 浏览数 (1)

全链路灰度目前是一个比较热门的技术栈,几乎是服务治理领域中必备的,所以咱们必须要搞清楚它,这样才能为自己的技术硬实力去添砖加瓦。假如现在让你去做好全链路灰度,你会怎么去做了,如果面试官这样去问你,你该怎么去回答呢?建议大家可以从如下三个方面去回答:

  • 什么是全链路灰度;
  • 如何去落地全链路灰度的解决方案;
  • 最后再来一次总结。
1.什么是全链路灰度?

建议你们可以从如下三点来回答。

(1)在解释这个概念之前,我们要先回顾一下单体架构中如何对应用中某个服务模块进行新版本发布,单体架构主要会包括如下模块:

  • 前端,前端主要是指暴露在公网上的APP;
  • 流量网关,流量网关主要是指Nginx、SLB等;
  • API, API主要是指对应的应用模块的Restful API服务;
  • 应用,应用会包括多个模块,比如商品模块、订单模块、购物车模块等。
  • 数据库, 比如MySQL数据库。

比如我现在要发布一个购物车模块,由于它是应用的一部分,所以新版本上线时需要对整个应用进行编译、打包以及部署。服务级别发布问题变成了应用级别的发布问题,我们需要对应用的新版本而不是服务来实施有 效的发布策略。

目前,业界已经有非常成熟的服务发布方案,例如蓝绿发布和灰度发布。蓝绿发布需要对服务的新版本进行冗余部署,一般新版本的机器规格和数量与旧版本保持一致,相当于该服务有两套完全相同的部署环境,只不过此时只有旧版本在对外提供服务,新版本作为热备。当服务进行版本升级时,我们只需将流量全部切换到新版本即可,旧版本作为热备。

在蓝绿发布中,由于存在流量整体切换,所以需要按照原服务占用的机器规模为新版本克隆一套环境,相当于要求原来1倍的机器资源。灰度发布的核心思想是根据请求内容或者请求流量的比例将线上流量的一小部分转发至新版本,待灰度验证通过后,逐步调大新版本的请求流量, 是一种循序渐进的发布方式。

(2)在分布式微服务架构中,应用中被拆分出来的子服务都是独立部署、运行和迭代的。单个服务新版本上线时,我们再也不需要对应用整体进行发版,只需关注每个微服务自身的发布流程即可。

如果此时是购物车服务去调用订单服务,为了验证订单服务的新版本,流量在整个调用链路上能够通过某种方式有选择的路由到订单服务的灰度版本,这属于微服务治理领域中流量治理问题。常⻅的治理策略包括基于 Provider 和基于 Consumer 的方式,我们可以去做如下事情:

  • 基于Provider的治理策略。配置订单服务的流量流入规则,购物车服务路由到订单服务时使用订单服务的流量流入规则;
  • 基于Consumer的治理策略。配置购物车服务的流量流出规则,购物车服务路由到订单服务时使用购物车的流量流出规则。

(3)全链路灰度

全链路灰度是一种端到端的灰度发布方案,全链路灰度治理策略主要专注于整个调用链,它不关心链路上经过具体哪 些微服务,流量控制视⻆从服务转移至请求链路上,仅需要少量的治理规则即可构建出从网关 到整个后端服务的多个流量隔离环境,有效保证了多个亲密关系的服务顺利安全发布以及服务多版本并行开发,进一步促进业务的快速发展。

2.如何去落地全链路灰度的解决方案呢?

如何在实际业务场景中去快速落地全链路灰度呢?目前,主要有两种解决思路,基于物理环境隔离和基于逻辑环境隔离。

(1)物理环境隔离

物理环境隔离,顾名思义,通过增加机器的方式来搭建真正意义上的流量隔离。这种方案需要为要灰度的服务搭建一套网络隔离、资源独立的环境,在其中部署服务的灰度版本。由于与正式环境隔离,正式环境中的其他服务无法访问到需要灰度的服务,所以需要在灰度环境中冗余部署这些线上服务,以便整个调用链路正常进行流量转发。此外,注册中心等一 些其他依赖的中间件组件也需要冗余部署在灰度环境中,保证微服务之间的可⻅性问题,确保获取的节点IP地址只属于当前的网络环境。

这个方案一般用于企业的测试、预发开发环境的搭建,对于线上灰度发布引流的场景来说其灵活性不够。况且,微服务多版本的存在在微服务架构中是家常便饭,需要为这些业务场景采用堆机器的方式来维护多套灰度环境。如果生产环境中应用数目过多的情况下,会造成运维、机器成本过大,成本和代价远超收益;如果应用数目很小,就两三个应用,这个方式还是很方便的,可以接受的。

(2)逻辑环境隔离

另一种方案是构建逻辑上的环境隔离,我们只需部署服务的灰度版本,流量在调用链路上流转时,由流经的网关、各个中间件以及各个微服务来识别灰度流量,并动态转发至对应服务的灰度版本。

  • 那么全链路灰度具体是如何实现呢?通过上面的讨论,我们需要解决以下问题:链路上各个组件和服务能够根据请求流量特征进行动态路由;
  • 需要对服务下的所有节点进行分组,能够区分版本;
  • 需要对流量进行灰度标识、版本标识;
  • 需要识别出不同版本的灰度流量。

如果采用逻辑环境隔离,我会采用如下技术手段去实现:

(1)标签路由;

标签路由通过对服务下所有节点按照标签名和标签值不同进行分组,使得订阅该服务节点信息 的服务消费端可以按需访问该服务的某个分组,即所有节点的一个子集。服务消费端可以使用 服务提供者节点上的任何标签信息,根据所选标签的实际含义,消费端可以将标签路由应用到 更多的业务场景中。

(2)节点打标;

那么如何给服务节点添加不同的标签呢?在如今火热的云原生技术推动下,大多数业务都在积 极进行容器化改造之旅。这里,我就以容器化的应用为例,介绍在使用Kubernetes Service 作 为服务发现和使用比较流行的 Nacos 注册中心这两种场景下如何对服务 Workload 进行节点打标。

在使用Kubernetes Service 作为服务发现的业务系统中,服务提供者通过向 ApiServer 提交 Service 资源完成服务暴露,服务消费端监听与该 Service 资源下关联的 Endpoint 资源,从 Endpoint 资源中获取关联的业务 Pod 资源,读取上面的 Labels 数据并作为该节点的元数据信息。所以,我们只要在业务应用描述资源 Deployment 中的 Pod 模板中为节点添加标签即可。

在使用Nacos 作为服务发现的业务系统中,一般是需要业务根据其使用的微服务框架来决定打标方式。 如果 Java 应用使用的 Spring Cloud Alibaba微服务开发框架,我们可以为业务容器添加对应 的环境变量来完成标签的添加操作。比如我们希望为节点添加版本灰度标,那么为业务容器添 加spring.cloud.nacos.discovery.metadata.version=gray,这样框架向 Nacos 注册该节点时 会为其添加一个标签verison=gray。

(3)流量染色

请求链路上各个组件如何识别出不同的灰度流量?答案就是流量染色,为请求流量添加不同灰 度标识来方便区分。我们可以在请求的源头上对流量进行染色,前端在发起请求时根据用户信 息或者平台信息的不同对流量进行打标。如果前端无法做到,我们也可以在微服务网关上对匹 配特定路由规则的请求动态 添加流量标识。此外,流量在链路中流经灰度节点时,如果请求信 息中不含有灰度标识,需要自动为其染色,接下来流量就可以在后续的流转过程中优先访问服 务的灰度版本。

(4)分布式链路追踪

还有一个很重要的问题是如何保证灰度标识能够在链路中一直传递下去呢?如果在请求源头染色,那么请求经过网关时,网关作为代理会将请求原封不动的转发给入口服务,除非开发者在 网关的路由策略中实施请求内容修改策略。接着,请求流量会从入口服务开始调用下一个微服 务,会根据业务代码逻辑形成新的调用请求,那么我们如何将灰度标识添加到这个新的调用请 求,从而可以在链路中传递下去呢?

从单体架构演进到分布式微服务架构,服务之间调用从同一个线程中方法调用变为从本地进程 的服务调用远端进程中服务,并且远端服务可能以多副本形式部署,以至于一条请求流经的节 点是不可预知的、不确定的,而且其中每一跳的调用都有可能因为网络故障或服务故障而出错。 分布式链路追踪技术对大型分布式系统中请求调用链路进行详细记录,核心思想就是通过一个 全局唯一的 traceId 和每一条的 spanId 来记录请求链路所经过的节点以及请求耗时,其中 traceId 是需要整个链路传递的。

对于分布式链路追踪,其实我可以建议大家去参考Skywalking,它是一个扩展性极高的Java体系的分布式链路追踪框架。

(5)逻辑环境隔离

需要支持动态路由功能,对于 Spring Cloud Alibaba和Dubbo RPC框架,可以对出口流量实现自定义 Filter,在该 Filter 中完成流量识别以及标签路由。同时需要借助分布式链路追踪技术完成 流量标识链路传递以及流量自动染色。此外,需要引入一个中心化的流量治理平台,方便各个 业务线的开发者定义自己的全链路灰度规则。

3.全链路灰度的总结

一般目前比较流行的是通过服务治理中的元数据去传递灰度标签,并在服务治理的负载均衡的过程中去识别标签,再读取对应标签的路由规则,从而实现全链路灰度。比如我们可以使用Spring Cloud Alibaba Nacos Dubbo去实现微服务体系中的全链路灰度,但是在Nginx层的灰度,也就是基于APP的灰度,还是需要咱们的APP层也具备灰度功能。

公众号初衷

知识输出是笔者的初衷,借助知识输出,能够认识更多的牛人,能够和牛人沟通,也是自己技术提升的一个机会。

0 人点赞