当前位置: 首页 > news >正文

通过 MSE 实现基于Apache APISIX的全链路灰度

什么是全链路灰度?

微服务体系架构中,服务之间的依赖关系错综复杂,有时某个功能发版依赖多个服务同时升级上线。我们希望可以对这些服务的新版本同时进行小流量灰度验证,这就是微服务架构中特有的全链路灰度场景,通过构建从网关到整个后端服务的环境隔离来对多个不同版本的服务进行灰度验证。

在发布过程中,我们只需部署服务的灰度版本,流量在调用链路上流转时,由流经的网关、各个中间件以及各个微服务来识别灰度流量,并动态转发至对应服务的灰度版本。如下图:

上图可以很好展示这种方案的效果,我们用不同的颜色来表示不同版本的灰度流量,可以看出无论是微服务网关还是微服务本身都需要识别流量,根据治理规则做出动态决策。当服务版本发生变化时,这个调用链路的转发也会实时改变。相比于利用机器搭建的灰度环境,这种方案不仅可以节省大量的机器成本和运维人力,而且可以帮助开发者实时快速的对线上流量进行精细化的全链路控制。

那么全链路灰度具体是如何实现呢?通过上面的讨论,我们需要解决以下问题:

1.链路上各个组件和服务能够根据请求流量特征进行动态路由

2.需要对服务下的所有节点进行分组,能够区分版本

3.需要对流量进行灰度标识、版本标识

4.需要识别出不同版本的灰度流量

下面将借着介绍 OpenSergo 对于流量路由所定义的 v1alpha1 标准,来告诉大家实现全链路灰度所需的技术细节。

Q:OpenSergo 是什么?
A:OpenSergo 是一套开放、通用的、面向分布式服务架构、覆盖全链路异构化生态的服务治理标准,基于业界服务治理场景与实践形成服务治理通用标准。OpenSergo 的最大特点就是以统一的一套配置/DSL/协议定义服务治理规则,面向多语言异构化架构,做到全链路生态覆盖。无论微服务的语言是 Java, Go, Node.js 还是其它语言,无论是标准微服务或 Mesh 接入,从网关到微服务,从数据库到缓存,从服务注册发现到配置,开发者都可以通过同一套 OpenSergo CRD 标准配置针对每一层进行统一的治理管控,而无需关注各框架、语言的差异点,降低异构化、全链路服务治理管控的复杂度

Q:为什么了解全链路灰度之前先给我介绍 OpenSergo?
A:OpenSergo 定义了一套统一的 YAML 配置方式来针对分布式架构进行全链路的服务治理的规范,介绍规范与标准的同时,我们可以了解其中的技术细节的实现,同时我们还可以将新的组件与 OpenSergo 的标准进行实现。

OpenSergo 流量路由 v1alpha1 标准

流量路由,顾名思义就是将具有某些属性特征的流量,路由到指定的目标。流量路由是流量治理中重要的一环,开发者可以基于流量路由标准来实现各种场景,如灰度发布、金丝雀发布、容灾路由、标签路由等。

全链路灰度示例:

流量路由规则(v1alpha1) 主要分为三部分:

  • Workload 标签规则 (WorkloadLabelRule):将某一组 workload 打上对应的标签,这一块可以理解为是为 APISIX 的各个上游打上对应的标签
  • 流量标签规则 (TrafficLabelRule):将具有某些属性特征的流量,打上对应的标签
  • 按照 Workload 标签和流量标签来做匹配路由,将带有指定标签的流量路由到匹配的 workload 中

我们可以赋予标签不同的语义,从而实现各个场景下的路由能力。

给流量打标:

需要将具有某些属性特征的流量,打上对应的标签。

假设现在需要将内部测试用户灰度到新版主页,测试用户 uid=12345,UID 位于 X-User-Id header 中:

apiVersion: traffic.opensergo.io/v1alpha1
kind: TrafficLabelRule
metadata:
  name: my-traffic-label-rule
  labels:
    app: my-app
spec:
  selector:
    app: my-app
  trafficLabel: gray
  match:
  - condition: "=="    # 匹配表达式
    type: header       # 匹配属性类型
    key: 'X-User-Id'   # 参数名
    value: 12345       # 参数值
  - condition: "=="
    value: "/index"
    type: path

通过上述配置,我们可以将 path 为 /index,且 uid header 为 12345 的 HTTP 流量,打上 gray 标,代表这个流量为灰度流量。

给 Workload 打标签:

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

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

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

对于一些复杂的 workload 打标场景(如数据库实例、缓存实例标签),我们可以利用 WorkloadLabelRule CRD 进行打标。示例:

apiVersion: traffic.opensergo.io/v1alpha1
kind: WorkloadLabelRule
metadata:
  name: gray-sts-label-rule
spec:
  workloadLabels: ['gray']
  selector:
    app: my-app-gray

流量染色:

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

目前在 OpenSergo v1alphal1 并未详细定义流量染色这一块的标准,可以后续社区一起讨论来设计流量染色标准。Apache APISIX 也会适配实现 OpenSergo 的标准,开发者可以通过同一套 OpenSergo CRD 标准配置针对流量网关层进行统一的治理管控,可以释放基于 Apache APSIX 的微服务架构的新价值。

全链路灰度是微服务最核心的功能之一,也是云上用户在微服务化深入过程中必须具备的功能。全链路灰度因为涉及到的技术和场景众多,如果企业一一进行自我实现,需要花费大量人力成本对其进行扩展与运维。

基于 Apache APISIX 全链路灰度方案产品实践

介绍完技术,下面来介绍一下阿里云上基于 Apache APISIX 的全链路灰度的产品实践。

前提条件

第一步:安装 Ingress-APISIX 组件

APISIX 架构如下图所示,我们需要安装 APISIX。

1.安装 apisix、apisix-ingress-controller、etcd 等组件

helm repo add apisix https://charts.apiseven.com
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
kubectl create ns ingress-apisix
helm install apisix apisix/apisix \
  --set gateway.type=LoadBalancer \
  --set ingress-controller.enabled=true \
  --set etcd.persistence.storageClass="alicloud-disk-ssd" \
  --set etcd.persistence.size="20Gi" \
  --namespace ingress-apisix \
  --set ingress-controller.config.apisix.serviceNamespace=ingress-apisix
kubectl get service --namespace ingress-apisix

看到在 ingress-apisix命名空间下看到无状态 apisix、apisix-ingress-controller 应用、以及有状态的 etcd 应用

2.安装 APISIX Admin

helm repo add apisix https://charts.apiseven.com
helm repo update
helm install apisix-dashboard apisix/apisix-dashboard --namespace ingress-apisix

安装完成后,可以绑定一个 SLB

通过{slb-ip}:9000 访问 APISIX 控制台(默认密码admin/admin)

第二步:开启微服务治理

这一步骤中,需要开通 MSE 微服务治理、安装 MSE 服务治理组件(ack-onepilot)并为应用开启微服务治理。具体操作信息可参考阿里云官方教程:https://help.aliyun.com/product/123350.html

第三步:部署 Demo 应用程序

在阿里云容器服务中部署 A、B、C 三个应用,每个应用分别部署⼀个base 版本和⼀个gray 版本;并部署⼀个 Nacos Server 应用,用于实现服务发现。具体可参考此教程完成应用部署:部署Demo 应用程序。部署完成后,你可以通过 APISIX Dashboard 为应用配置 Service 进行上游配置。

应用场景:按照指定请求参数进行路由,实现全链路灰度

有些客户端没法改写域名,希望能访问 http://www.demo.com 通过传入不同的参数来路由到灰度环境。例如下图中,通过 env=gray 这个请求参数,来访问灰度环境。

调用链路 Ingress-APISIX -> A -> B -> C ,其中 A 可以是一个 spring-boot 的应用。

配置 APISIX 路由规则

在 APISIX Dashboard 选择路由并单击创建。匹配条件中新建高级匹配规则、请求路径选择 /*,选择对应的上游。分别配置如下路由:

  • 当 host 为 http://www.demo.com,请求参数 env=gray 时,路由优先匹配 id 为 401163331936715388 所对应的上游,即 spring-cloud-a-gray-svc;
  • 当 host 为 http://www.demo.com 时,路由经会匹配 id 为 401152455435354748 所对应的上游,即 spring-cloud-a-svc。

然后进行 base 对应的路由配置:

{
  "uri": "/*",
  "name": "spring-cloud-a",
  "methods": [
    "GET",
    "POST",
    "PUT",
    "DELETE",
    "PATCH",
    "HEAD",
    "OPTIONS",
    "CONNECT",
    "TRACE"
  ],
  "host": "www.demo.com",
  "upstream_id": "401152455435354748",
  "labels": {
    "API_VERSION": "0.0.1"
  },
  "status": 1
}

进行 gray 对应的路由配置,如下图所示:

{
  "uri": "/*",
  "name": "spring-cloud-a-gray",
  "priority": 1,
  "methods": [
    "GET",
    "POST",
    "PUT",
    "DELETE",
    "PATCH",
    "HEAD",
    "OPTIONS",
    "CONNECT",
    "TRACE"
  ],
  "host": "www.demo.com",
  "vars": [
    [
      "arg_env",
      "==",
      "gray"
    ]
  ],
  "upstream_id": "401163331936715388",
  "labels": {
    "API_VERSION": "0.0.1"
  },
  "status": 1
}

配置 MSE 全链路灰度

你需要配置完成 MSE 的全链路发布,具体操作细节可参考此教程:配置全链路灰度。

结果验证

此时,访问 http://www.demo.com 路由到 基线环境

curl -H"Host:www.demo.com" http://47.97.253.177/a
A[172.18.144.15] -> B[172.18.144.125] -> C[172.18.144.90]%

此时,访问 http://www.demo.com 同时env=gray时路由到灰度环境

curl -H"Host:www.demo.com" http://47.97.253.177/a?env=gray
Agray[172.18.144.16] -> Bgray[172.18.144.57] -> Cgray[172.18.144.157]%

注意:其中 47.97.253.177 为 APISIX 的公网 IP

总结

目前 MSE 服务治理全链路灰度能力已经支持了云原生网关、ALB、APISIX、Apache Dubbo、Spring Cloud、RocketMQ 以及数据库。

基于 Apache APISIX 灵活的路由能力,配合 MSE 全链路灰度能力,可以快速实现企业级的全链路灰度的能力。APSIX 支持按照 Header、Cookie、Params、域名等多种方式进行路由,只需要在网关侧根据需求将流量路由至不同的“泳道”环境后,流量在对应标签的“泳道”中自动闭环,当泳道中并不存在调用链中所依赖的其他服务时,流量需要回退至基线环境,进一步在必要的时候路由回对应标签的泳道。

服务治理是微服务改造深入到一定阶段之后的必经之路,在这个过程中我们不断有新的问题出现。

  • 除了全链路灰度,服务治理还有没其他能力?
  • 服务治理能力有没一个标准的定义,服务治理能力包含哪些?
  • 多语言场景下,有无全链路的最佳实践或者标准?
  • 异构微服务如何可以统一治理?

当我们在探索服务治理的过程中,我们在对接其他微服务的时候,我们发现治理体系不同造成的困扰是巨大的,打通两套甚者是多套治理体系的成本也是巨大的。为此我们提出了 OpenSergo 项目。OpenSergo 要解决的是不同框架、不同语言在微服务治理上的概念碎片化、无法互通的问题。

相关链接

  • OpenSergo:https://opensergo.io/zh-cn
  • MSE 微服务引擎:https://www.aliyun.com/product/aliware/mse

作者:十眠

原文链接

本文为阿里云原创内容,未经允许不得转载。

相关文章:

  • 神经网络优化算法有哪些,人工神经网络优化算法
  • 使用python-docx完成word操作
  • Interactive Tools Recommendation System integrating QT/ROS /Pytorch
  • 嵌入式属于人工智能吗?
  • Linux操作系统——进程控制【一】
  • 鸡葡萄菌感染怎么防治 预防鸡感染球菌病吃啥药
  • 技术分享 | App测试时常用的adb命令你都掌握了哪些呢?
  • 鸡得关节炎有哪些症状 鸡喂什么药预防球菌病
  • Dockerfile的使用-利用docker构建包含jdk ,vim centos
  • LeetCode-946-验证栈序列
  • vnc服务
  • Js各种时间转换问题(YYYY-MM-DD 时间戳 中国标准时间)
  • 李迟2022年8月工作生活总结
  • 百度 T4 幕后揭秘!这份 Java 面试全栈手册竟让面试官节节败退
  • 干货分享:有什么软件可以让照片动起来?
  • gcc介绍及安装
  • java小心机(3)| 浅析finalize()
  • nodejs实现webservice问题总结
  • Redis 中的布隆过滤器
  • Spring Cloud Feign的两种使用姿势
  • 阿里云应用高可用服务公测发布
  • 大数据与云计算学习:数据分析(二)
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 七牛云假注销小指南
  • 前端技术周刊 2019-02-11 Serverless
  • 山寨一个 Promise
  • 使用 Node.js 的 nodemailer 模块发送邮件(支持 QQ、163 等、支持附件)
  • 收藏好这篇,别再只说“数据劫持”了
  • 数据科学 第 3 章 11 字符串处理
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 关于Kubernetes Dashboard漏洞CVE-2018-18264的修复公告
  • 如何正确理解,内页权重高于首页?
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​用户画像从0到100的构建思路
  • #pragma multi_compile #pragma shader_feature
  • (BFS)hdoj2377-Bus Pass
  • (Git) gitignore基础使用
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (vue)页面文件上传获取:action地址
  • (笔试题)分解质因式
  • (博弈 sg入门)kiki's game -- hdu -- 2147
  • (定时器/计数器)中断系统(详解与使用)
  • (多级缓存)多级缓存
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)ssm考试题库管理系统 毕业设计 069043
  • (四)c52学习之旅-流水LED灯
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • .Net 代码性能 - (1)
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .NET/MSBuild 中的发布路径在哪里呢?如何在扩展编译的时候修改发布路径中的文件呢?
  • /dev/sda2 is mounted; will not make a filesystem here!