开发者学堂课程【MSE 流量治理的最佳实践:全链路灰度在数据库上我们是怎么做的?】学习笔记,与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1068/detail/15512
全链路灰度在数据库上我们是怎么做的?
内容介绍:
一、大纲
二、为什么微服务的流量需要治理
三、 OpenSergo 流量治理的 v1alph1 标准
四、 MSE 企业版的流量治理能力
五、 Demo 演示: MSE 数据库流量灰度的实践
今天的一个主题是 MSE 流量治理的一个最佳实践。那现在可以回顾一下软件技术的发展,从最开始的单体应用逐渐演进到分布式应用,也随着微服务理念的兴起,让大规模高并发低延迟的分布式应用成为可能。但其实微服务架构也是一把双刃剑,随着微服务架构的复杂化。在大规模之下,再小的问题其实都是会牵一发而动全身,因此随着微服务架构的增长,如果不对微服务进行恰当的治理,那么微服务架构带来的效率稳定性的问题可能会远大于微服务本身带来的价格红利。那么今天的主题,其实就是关于阿里云在微服务治理场景下的一个流量治理的一个最佳实践,当然内容不包含于流量治理的线路降级、权威度以及灰度等各个场景。
一、大纲
当然今天分享会从流量治理讲到最近开源的一个 OpenSergo 在流量治理这一块的一个标准的定义,然后最后会提一下 MSE 企业版在流量治理中的一个能力,那最后也会带来一个简单的一个 demo ,就是说演示一下 MSE 最近一个新的一个功能:关于数据库的流量灰度的实践。
二、为什么微服务的流量需要治理
现在第一块来介绍一下为什么微幅的流量需要治理,首先先讲一下为什么微服务这一块有需要一个治理,也就是说先不讲微服务流量。
1.微服务架构中的新四大件
在传统的微服务心智里面,大多数人可能都会认为微服务治理的架构包含三块东西,分别是服务提供者、服务消费者还有注册中心。但是现在看来,其实微服务架构中的一个四大件应该是服务提供者、服务消费者、注册中心以及治理中心。那么治理中心的作用其实就是对微服务领域的各个组件进行治理。微服务治理其实就是通过像全流路灰度、无损上线、流控降级、异常流量调度、数据库治理、缓存治理、日志治理等技术手段来减少甚至避免发布和管理大规模应用过程中的遇到一系列的稳定性问题、成本以及效率等问题,然后对微服务领域的各个组件进行治理。站在现在的视角来看,其实服务提供者、服务消费者、注册中心、微服务治理中心构成了现代微服务架构中的重要的几环。
2.安全变更
那在一些场景上要提,就是如果在稳定性方面其实可以考虑到在安全方面有一个安全变更三板斧的要求,这里面其实就提到可灰度、可监控、可回滚,在这个过程中其实就可以看到对流量治理的一个灰度能力的一个诉求以及流量监控的一个诉求。同时在故障应急的医务室原则中,其实是有要求的:一分钟发现、五分钟定位、十分钟恢复。然后这里其实涉及到一系列的最佳实践以及操作的一些原则或者说是一个制度上的一些策略,比如像发布过程中的封网、变更的管控、故障的应急、故障复盘、紧急发布以及阿里内部可以有一个稳定性分的概念。同时在这个过程中其实也有各个方面来保证一个安全变更的一个效果。
3.标签路由
那其实在这个过程中,就体现了一些在流量层面的一系列能力,比如说标签路由。标签路由,这里的标签其实可以理解为他就是一个流量路由的场景,在这个过程中,其实当标签富含不同的语义的时候,这个就可以实现不同场景的一个路由的一个能力。比如像标签路由金丝雀发布,当这个标签的含义是版本标的话,他实现的就是一个金丝雀发布的一个含义。
4.开发环境隔离
然后下面可以看一下详细的场景,比如像开发的一个环境隔离,就是对流量的标签打上一个开发环境的一个 tag 的标,其实他就可以做到一个环境的一个逻辑上的隔离,这样对开发环境的隔离的一个效果可以带来巨大的一个成本和运维的一个资源的成本以及运维成本的一个下降。这样的话,也就是说可以快速拉起一套新的一个开发环境。对于研发同学来说,也是敏捷开发的一个非常好的一个场 景。在这一块,其实可以看到最重要的一个能力,就是对服务的流量进行一个路由;然后同样的,先是进行一个染色,再去进行一个路由,从而实现一个逻辑的一个环境隔离,达到一个泳道的效果。
5.灰度的更多场景
那同时在这个过程中,灰度其实还有更多的场景。比如像秒杀,秒杀日常订单的流量,然后同时也有秒杀的流量,可以让秒杀的流量进入到一个灰度,其实是一个全链路灰度的一个场景。那同时也可以有一个地域的区分,假设B地域的用户,他的流量可以优先打到B地域的一个应用里面,其实也可以做到一个这样的一个场景。
6.流量稳定性与容错治理—背景
(1)流量激增:那么同时在流量方面,不仅仅是有流量路由,还有流量的稳定性与容错的一个治理。比如像场景中的服务依赖,其实他是非常重的,在这个过程中当下游出现一些不稳定的一个服务依赖,他可能会导致上游的服务被拖垮。那么同时,对于一些服务的容量其实是有限的,但是流量本身他的随机性是非常大的,那么激增的流量很可能会导致系统的CPU 和 Load 彪高,从而使得整个系统被拖垮,使他无法正常的处理请求。同时当应用在发布的过程中或者说特别是在原生环境下,一般会对服务配置一个 HPA 的能力,就是说此服务具备弹性扩缩容的能力;那么如果是激增的流量,他可能会打垮一个冷的系统,就是说当应用 PoT 刚扩容出来的时候,他的容量其实是远低于正常容量的,这个时候的正常流量很可能会打均分到这个 PoT 上面,从而会导致他的一个流量无法正常的请求,从而导致服务的一个稳定性的一个问题。同时在异步的场景下,消息的投递速度过快,可能会导致消息处理的一个积压。
(2)不稳定服务依赖:在不稳定服务依赖方面,比如像慢 SQL 查询会导致数据库连接池被卡死;同时如果第三方服务出现不稳定或者说不响应的时候,很可能会拖垮的线程池;同时也有一些不重要的服务,比如一些弱依赖的服务,他出现问题的时候可能会拖垮上游重要的一些服务,而有的时候业务调用出现持续的一个异常会产生大量的一个副作用,那这所有的问题其实都是一个需要对流量的稳定性与容错进行一个治理的。
7.流量控制:防止突发流量将业务打垮
(1)业务场景/痛点:下面就会举一些这方面的具体的场景,比如像流量控制,可能需要做到流量控制的一个目的就是防止突发的流量将业务打垮。比如像一些业务场景的一些痛点,比如像当电商大促的时候,某个时刻像双11这样一个系统,可能在零点的时候有巨大一个的洪流量,洪峰也就是抢购或者说秒杀等服务可能会直接把系统给卡死,因为他的流量可能是之前的数百倍,甚至是上千倍;那如果服务在此之前没有做到很好的预热以及流量控制的话,其实他很可能会把我们的系统给打挂。同时要对服务间的一个依赖,可能是需要进行一些细粒度的管理。比如说服务 A 是调用来源有服务 B 跟服务 C ,其中服务 C 是比较重点的业务,就需要优先保证他的调用;但服务 B 有时候会有较大的并发调用从而导致重点业务的一个流量资源被抢占,从而影响整体系统的一个稳定性。
(2)解决方式:那么解决方案,其实可以想到如果有流量控制的能力的话,可以通过流量控制能力为服务的接口配置一些流量控制的一些规则,让容量在一定的范围内通过多余的请求被拒绝,这其实就相当于一个安全气囊的作用。层层保护,从网关层到微服务,再到接口,都可以进行细粒度的参数配置,这样的话就可以保证服务不会被拖垮。即使是流量不大的情况下,也很难保证流量他是一个稳定的情况。
8.热点控制:防止非预期内的热点流量将业务打垮
(1)业务场景/痛点:在流量治理中,其实还有一个比较核心的一个能力,可以想到的就是热点流控,为什么会有这样的场景呢?其实可以想象一些业务场景,比如说在大促的过程中,整体的用户量其实是可以的,但是在这个过程中可能突然出现一些黑马或者是一些热点商品。当然对于这些热点的商品,事先是无法预知的,但是这些热点的流量很可能会击穿缓存并把数据库给打挂了,从而影响正常的一个流量的一个业务处理。那么同时在网关侧可能会希望针对某个用户或者某些IP进行一些热点防刷的能力,比如像一些薅羊毛的用户,可能他会一直在刷,那么针对这些用户可以对他进行限流从而使得正常的一个用户流量可以直接通过。
(2)解决方式:通过热点参数流控能力,自动识别参数中的 Top N 访问热点的参数值,并对这些参数进行单独流控,避免单个热点访问过载;并且可以针对一些特殊热点访问(如极热门的抢购单品)配置单独的流控值。而参数可以是任何业务属性,可以来自调用端 IP 、 RPC 参数、 HTTP 请求参数、 header 等,也支持自定义。
9.服务并发隔离:保障调用端稳定性,避免级联故障
(1)业务场景/痛点:当然在流量隔离过程中,其实还有一些像服务并发的一个隔离来保调用端的稳定性,避免一些级联故障。比如说慢 SQL 或者说下游服务不稳定,其实之前也提到了。
(2)解决方式:当流量近似稳态时:并发线程数= QPS * RT(s); RT 升高,并发线程数升高,代表服务调用出现堆积。采用流量治理提供的服务并发隔离能力,给重要服务调用配置并发线程数限制,相当于一道“软保险”,防止不稳定服务过多挤占正常服务资源。
10.服务熔断与降级:保护重点业务、降级非重点业务
那么在这个场景下,其实还有熔断与降级的一个场景。比如说熔断的话,可能会因为下游不稳定的一个服务而导致上游的服务也出现问题,同时也有一些不重要的服务频繁地调用资源从而导致重要的服务可能也会出现问题。所以说特别是在大促的时候,可能要临时降级掉一些弱依赖的服务调用,把资源保留给其他核心服务,从而保证整体的一个业务的顺畅。
三、 OpenSergo 流量治理的 v1alph1 标准
上面讲的这一系列的流量治理的场景,可以想到就是说如果没有对流量进行一个恰当的治理,那么所有以上提到的这些不稳定的场景都可能会导致一些严重的后果。那么如何能做到流量控制从而可以保证流量均匀平滑的一个用户访问,或者如何预防流量过大,又或者说预防服务不稳定带来的一些影响。那么全链路灰度以及向日常环境隔离这些场景里面是如何做到的呢?下面将会通过 OpenSergo 流量治理的 v1alph 1的一个标准来针对以上微服务流量治理中常用到的两个大的场景进行一个详细的介绍。
1. OpenSergo 定位
(1)含义:在这个过程中,先简单的介绍一下 OpenSergo ,什么是 OpenSergo ? OpenSergo 的定位就是一套开放的、通用的、面向分布式应用、覆盖全链路异构化生态的服务治理的一个标准与参考实现。
(2)特点:他有四个特点。首先是标准化,就是基于业界服务治理的场景与实践抽象成通用的标准,以统一的服务协议以及 YAML CRD 标准配置进行管控,降低用户上云与维护的成本。第二个特点是一个多元的一个异构化的特点,就是说希望的是一套统一通用的一个面向分布式应用的且是覆盖全链路异构化的服务治理的一个标准与实现。所以说无论微服务语言是 Java 、 go 、 Node.js 、Rust 还是说其他语言,也无论是传统的微服务还是说 Mesh 的架构,都可以用一套统一的标准规范进行接入从而降低整体实现与维护的成本。然后第三个特点就是一个全链路生态的一个覆盖,因为所有的功能其实都是端到端的体验,也就是说从网关到微服务,以及到数据库到缓存,从服务注册发现到服务配置,其实 OpenSergo 是针对了应用链路上的每一环都进行了抽象场景的覆盖,场景的一个完整的覆盖。最后一个特点就是 OpenSergo 是一套开放的一个协议,所以也是联合了多家企业以及各个社区进行共同合作,比如像 B 站,还有字节等企业,是一起推出的 OpenSergo 。然后同时希望这一块是社区参与共建,就是说业界共建的一套开放的一个标准协议即标准的治理。同时也需要各个社区来进行一个实现参考的实现。
2.贯穿微服务领域的 OpenSergo
上面讲了 OpenSergo 其实是贯穿微服务领域的一个 OpenSergo,可以看到他的标准其实有覆盖流量治理,服务容错其实也是流量治理里面的一环。流量治理、数据库治理、缓存治理、配置治理、服务员数据、服务发现以及可观测的分布式日志, MQ 等各个治理的领域,然后在他中间其实是有一套各个语言的一个 OpenSergo 的一个 SDK 或者说是 Mesh 的一个接入方案。然后可以看到下面是全方位的覆盖各个服务的各个生态,有注册中心、有网关、有微服务、有 Mesh 、有数据库、也有缓存、应用配置、消息队列等。
3. OpenSergo 项目结构
然后这里是 OpenSergo 的一个项目的结构;可以看到最上层是一个OpenSergo 的一个 Spec ,在这里其实就是之前提到的各个领域的一个标准的一个规范,可以理解为他是一个配置或者说脚本式的一个语言;然后在中间这一层其实就是一个 OpenSergo 的一个 SDK ,他提供了 Spec 的一个对接的 API ,当然有 Java 、有GO、也有各个语言实现的对接的一个 SDK ;再往下一层就是各种开源的一个生态。 OpenSergo 主要是分为这几个部分,总结一下其实就是一个OpenSergo 的一个 Spec 是统一的服务协议与 CRD 的一个标准定义;第二个就是 OpenSergo 的一个多语言的一个 SDK 来提供统一的一个标准的 CRD 对接模块,提供各个框架组件来对接OpenSergo 的一个 Spec ;然后第三个可以理解为是一个OpenSergo 的一个数据面,是对 OpenSergo 的一个 Spec 的一个组件,其对接 OpenSergo Spec 的一个各种框架组件都可以用OpenSergo 的一个标准方式进行统一的治理。在这个过程中,其实是希望与各个社区进行合作共建,然后将更多的框架与组件对接到OpenSergo 的生态。可以想象一下,每个框架其实都是一个OpenSergo 的一个数据面,然后终端用户可以通过 OpenSergo 的一个 CRD 进行一个统一的治理管控。
4.统一的标准方式对完整的服务链路实现治理能力
下面就真正讲一下 OpenSergo 的一个标准的一个样子,也就是今天的主题就是流量治理,那就讲一下 OpenSergo 流量治理一个样子。那么通过这张图,其实可以看到一个想法,就是说希望以一个统一的一套配置或者 DSL 或者说协议来定义服务治理的一个规则。同时是面向多源异构化的架构,希望是做到全链路的生态的一个覆盖。
5.流量治理标准化
这里有一个标准,其实是抽象成的一个样子,就可以理解为是一个这样的样子即用户通过一个 CRD 的一个配置或者说是 OpenSergo 的一个控制台的配置,然后 OpenSergo 的规则就会转化为系统定义的一些路由的能力。当然这边可以是 Spring Cloud Alibaba ,也可以是各个生态,然后下面可以看到他其实是对接了各个生态的一个实现。
6. OpenSergo 流量路由 Spec
那下面就讲一下 OpenSergo 的具体的一个 Spec ,其实通过这一块的配置也可以理解到在流量路由这一块的一个实现。首先对流量路由的过程抽象成两个过程,一个是对一定条件的流量进行标签的划分,第二块就是说对 workload 进行一个标签的划分。那其实在这中间就可以看到就是对应标签的流量会自动的路由至指定的一个 workload 。可以看到中间的一个 CRD 的一个标准,首先上面是一个 workload 的一个打标,可以认为是对 APP 、也可以是对数据库进行一个 gray 的一个配置;然后再看最右边就是一个 TrafficLabe 的一个 rule ,其实可以看到这边他的一个配置也就是说对 header 中的 key 是 X-user-Id 为12345的,并且它的路径是 /Index 的流量进行匹配,进行一个标签划分,划分到一个gray 的标签。右下角这样的图里这样的一个规律的流量就会被自动的路由至指定的 Gary 的一个 workload ,其实就是一个 department ,当然这边可以是 Java 的应用,也可以是 go 语言的应用。言外之意像 user ID 不等于12345的,比如说666、888,他们其实是匹配不到标签的,那他们就是被路由默认的一个 department 的上面,这个就是流量路由的一个标准。
7. OpenSergo 流控降级与容错 Spec
下面再看一下 OpenSergo 的一个流控降级与容错的一个标准。可以看到对规则进行了三部分的一个抽象;首先就是 Target ,是针对怎么样的流量;第二块就是Strategy ,是对应的流量治理的一个策略;第三块就是 FallbackAction ,是说出发后的一个 Fallback 的行为。现在看右边的一个标准就可以理解了,就是说对 Flow 接口的应用的一个流量配置了一个 Rightlimit Flow 的一个规则以及熔断的一个规则。然后可以看到留空的这个规则其实他的配置无非就是说阈值是10,然后时间窗口是一秒,就是说每秒钟请求10的一个限流并且是一个全局的一个限流的规则。那第二块可以看到其实配置了一个融断的一个规则,他针对的比例是60%,窗口是30秒,恢复的时间是5秒,每秒超时的请求的次数是五,超时的时间即 RT 就是500毫秒也就说超过500毫秒的请求并且每秒钟的请求数是大于五他就会被隔离,同时他的统计窗口是30秒并且他的阈值是大于60%,他就会被隔离五秒。那当然这一块没有定义 Fallback Action ,那么默认可以是返回503,他可以返回503,也可以返回特定的 RPC 的一些 exception ,也可以流量调度至其他的节点。
四、 MSE 企业版的流量治理能力
然后讲完 OpenSergo 的一个流量治理的标准之后,就介绍 MSE 企业版。讲完 OpenSergo 的一个流量治理的标准,其实就介绍一下阿里云上完全支持的一个 OpenSergo标准的一个流量治理的实现: MC企业版。当然它的功能矩阵也不仅仅在流量治理这一块,他是从开发态、测试态到运行态,提供了基础治理能力和高阶治理能力的全生命周期的一个服务治理。
当然 MSE 最近也推出了企业版,其实可以看到企业版的价格其实相比流量防护的话,其实是价格是一致的,但是他有更加全面的恢复治理能力跟流量防护的一个能力。
五、 Demo 演示: MSE 数据库流量灰度的实践
现在来演示一下最近带来的一个新的功能,就是说全链路灰度在数据库上的一个实践。而且之前也都有问过,就是说全链路灰度支持 RPCMQ 在流量层面其实都已经支持了,那在数据层面应该怎么做呢?其实今天就这个 demo 就可以展示在数据库层面的一个实践。现在直接看演示的一个实践。首先这边准备了一个 demo ,还是大家一直看到的,就是说从做微服务网关到 spring-cloud-a 到 spring-cloud-b 再到 spring-cloud-c ,然后使用 nacos-server 来做服务发现,然后同时 abc 其实都有一个机械环境以及灰度环境的两个 department 。
然后在 MSE 上,其实可以看到一个对应的一个映射,就是说网关、 spring-cloud-a 、 spring-cloud-b 、 spring-cloud-c ,同时每个都是有两个服务。
这边打错标了,应该是一个灰度环境,一个 base 环境,刚才改了一下。可以看到为什么还在环境变量中加上一个 alicioud.service.header 其实就带上这个参数的话,他会把设定的业务参数可以从上往下透传下去,其实用的就是最佳时间里面的一个能力,就是将看到这个参数 alicioud.service.header = x-user-Id ,他可以将自定义的一个 header 来进行全链路的一个透传。现在将 location 这个 header 进行全链路的一个透传。
再看一下 a 应用,可以看到他这边现在已经是 gray 标和未达标是符合预期的。
现在 demo 准备好之后,就来开启一个 MSE 的一个全链路灰度的一个能力,左边已经创建好了一个泳道组把刚才的 demo 应用都圈进来,然后入口应用是是所有应用。
那同时在这个过程中,需要配置一个泳道的规则也就是说让 location等于 cn-shenzhen的一个流量,他是去往灰度的一个泳道,言外之意就是说不符合这个条件的流量就去往一个默认环境的泳道,那验证一下。
下面 Demo 的一个样子希望是这样。
就是灰度环境他可以访问数据库的话,其实是访问灰度的表;那机械环境他就是说访问一个机械的表;那在这个过程中看到这个拓扑的话言外之意就是如果要操作数据库、要灰度数据库环境的话,其实是需要首先要创建一个灰度表,在这个过程中,假设用到的一个demo是 mse_demo_table ,那接下来就需要创建跟他一一匹配的一个灰度的表。那这边已经提前串好了,现在两个表他其实都是空的,言外之意就是说灰度流量要操作哪张表就需要创建哪个表的一个对应的一个灰度表。
从这个操作看出来,其实使用的就是一个影子表的一个方案。接下来配好全链路流量的规则可以先验证一下全链路灰度在流量层面是否生效。假设现在的 location 是杭州,可以看到他访问的是 base 环境;那如果 location 等于 cn-shenzhen ,他其实是符合去往灰度环境的一个条件,可以看一下他是否生效,可以看到带着 headerlocation 是深圳,他其实就访问的是灰度环境;然后在 C 应用中进行操作无非就是将 location 进行入库。
“location:cn-hangzhou”
“location:cn-shenzhen”
再查询一下数据库表,可以看到灰度环境,他这边有个 location 是深圳
那机械环境的数据库表,他只是 location 是杭州。
那也就说明符合,当访问灰度环境的之后,他的流量就会操作灰度的数据库表;如果他不符合,其实他就操作线上表,那就假设CN等于 shanghai 。
“location:cn-shanghai”
其实他是不符合灰度条件所以他应该是访问 base 表,然后可以看到,上海应该是可以在机械环境的一个表中查到,果然是这样的一个道理。
通过一个简单的 demo 就快速的演示了一个全链路灰度能力在持续化层的一个操作。然后下面总结一下,首先需要配置一个全链路灰度的规则;然后需要灰度哪张表的时候,其实是需要在数据库中创建对应的一个环境的一个表,当然现在采用的规则,默认的是原来的表名加上下划线环境名,就会作为灰度环境的一个影子表或者说灰度表;然后当流量中带有灰度环境的标,那他所执行的对应的 SCG 操作都会针对灰度环境的一个表进行操作;同理,机械环境的话就是针对机械环境的表操作;然后整个 demo 就是这样的一个样子。以上是关于 MSE流量治理的介绍。如果有更多感兴趣的能力,也欢迎试用 MSE 的一个企业版;同时如果对数据库灰度有需求的话,也欢迎交流;最后再讲一下 MSE 企业版,他提供了更多的一个能力,除了原有的一个服务治理能力,他还新增了流控降级的能力,可以理解为是三层的一个商业化的一个版本,欢迎各位试用。