全链路灰度这样做,新需求迭代上线也能放心干饭

本文涉及的产品
Serverless 应用引擎免费试用套餐包,4320000 CU,有效期3个月
可观测监控 Prometheus 版,每月50GB免费额度
函数计算FC,每月15万CU 3个月
简介: MSE 的全链路灰度能力随着客户场景的深入而不断扩展与迭代,只有经过客户打磨的产品才会愈发历久弥新,欢迎大家尝鲜体验。

作者:泮圣伟(十眠)


概要


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


涉及到的技术领域


  • RPC: 微服务之间的路由
  • Java 体系涉及 Spring Cloud,Apache Dubbo 主流微服务框架,多语言涉及 Service Mesh
  • 端云互联场景,线上流量 DEBUG。本地通过跳板机将本地服务注册到注册中心,希望线上流量满足路由规则后路由到本地服务对于的实例上再进行 DEBUG,不满足路由规则的流量路由到线上实例


  • MQ
  • 全链路压测场景下,压测流量发送消息到影子 Topic,压测流量只订阅影子 Topic
  • 流量隔离/全链路灰度场景下,使用相同 Topic,线上流量订阅线上消息,隔离流量只订阅灰度消息


  • Database
  • 全链路压测场景下,压测流量数据落库到到影子表上
  • 高可用切流的场景下,禁止数据库操作;单元化下,流量没有单元标,禁止数据库操作


  • Redis
  • 全链路压测场景下,压测流量缓存落库到到影子 KEY 上
  • 高可用切流的场景下,禁止缓存操作;单元化下,流量没有单元标,禁止缓存操作


  • 分布式任务调度
  • 对于任务调度,灰度环境提交的任务,被调度到灰度环境的机器上执行


  • 前端
  • 不同客户看到的页面信息不一致


  • 可观测性
  • 通过可观测性监控流量走向,查看流量逃逸情况


MSE 全链路灰度解决方案


目前 MSE 服务治理专业版提供了完整的产品化的全链路灰度解决方案,覆盖 RPC、MQ、可观测性等绝大多数场景。只要您的架构是基于 Spring Cloud 或者 Dubbo 框架,您的应用无需升级,无需一行代码改动,即可玩转企业级全链路灰度功能。


  • 全链路隔离流量泳道

1) 通过设置流量规则对所需流量进行'染色','染色'流量会路由到灰度机器。

2) 灰度流量携带灰度标往下游传递,形成灰度专属环境流量泳道,无灰度环境应用会默认选择未打标的基线环境。


  • 端到端的稳定基线环境

未打标的应用属于基线稳定版本的应用,即稳定的线上环境。当我们将发布对应的灰度版本代码,然后可以配置规则定向引入特定的线上流量,控制灰度代码的风险。


  • 流量一键动态切流

流量规则定制后,可根据需求进行一键停启,增删改查,实时生效。灰度引流更便捷。


  • 可观测能力

具备泳道级别的单应用可观测能力
image.gif

1.png


同时具备全链路应用的可观测能力,可以从全局视角观察流量是否存在逃逸情况。灰没灰到,一目了然。
image.gif

2.png


  • 低成本接入,基于 Java Agent 技术实现无需修改一行业务代码

MSE 微服务治理能力基于 Java Agent 字节码增强的技术实现,无缝支持市面上近5年的所有 Spring Cloud 和 Dubbo 的版本,用户不用改一行代码就可以使用,不需要改变业务的现有架构,随时可上可下,没有绑定。只需开启 MSE 微服务治理专业版,在线配置,实时生效。


  • 具备无损上下线能力,使得发布更加丝滑

应用开启 MSE 微服务治理后就具备无损上下线能力,大流量下的发布、回滚、扩容、缩容等场景,均能保证流量无损。


如何使用 MSE 全链路灰度


接下来将演示全链路灰度的能力,我们使用应用的架构由 Ingress-nginx 以及后端的微服务架构(Spring Cloud)来组成,后端调用链路有3跳,购物车(a),交易中心(b),库存中心(c),客户端通过 客户端或者是 H5 页面来访问后端服务,他们通过 Nacos 注册中心做服务发现。


准备工作


开通 MSE 微服务治理专业版


登录 MSE 治理中心控制台,如果您尚未开通 MSE 微服务治理,请根据提示开通专业版。如果您已经开通了 MSE 微服务治理基础版,请根据概览页中右侧的提示,升级到 专业版。


安装 Ingress-nginx 组件


  1. 登录容器服务控制台[1]
  2. 在左侧导航栏选择市场 > 应用目录。
  3. 应用目录页面搜索框中输入 ack-ingress-nginx,单击image.gif图标,然后单击组件。
  4. 详情页面选择组件的命名空间kube-system,然后单击创建。安装完成后,在命名空间 kube-system 中出现 ack-ingress-nginx-default-controller 应用,表示安装成功。



部署 Demo 应用程序


将下面的文件保存到 ingress-gray-demo-deployment-set.yaml 中,并执行 kubectl apply -f ingress-gray-demo-deployment-set.yaml 以部署应用,这里我们将要部署 A, B, C 三个应用,每个应用分别部署一个基线版本和一个灰度版本。


# A 应用 base 版本
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-a
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-cloud-a
  template:
    metadata:
      annotations:
        msePilotCreateAppName: spring-cloud-a
      labels:
        app: spring-cloud-a
    spec:
      containers:
      - env:
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk/jre
        image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-a:0.1-SNAPSHOT
        imagePullPolicy: Always
        name: spring-cloud-a
        ports:
        - containerPort: 20001
        livenessProbe:
          tcpSocket:
            port: 20001
          initialDelaySeconds: 10
          periodSeconds: 30
# A 应用 gray 版本
---            
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-a-new
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-cloud-a-new
  strategy:
  template:
    metadata:
      annotations:
        alicloud.service.tag: gray
        msePilotCreateAppName: spring-cloud-a
      labels:
        app: spring-cloud-a-new
    spec:
      containers:
      - env:
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk/jre
        image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-a:0.1-SNAPSHOT
        imagePullPolicy: Always
        name: spring-cloud-a-new
        ports:
        - containerPort: 20001
        livenessProbe:
          tcpSocket:
            port: 20001
          initialDelaySeconds: 10
          periodSeconds: 30
# B 应用 base 版本
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-b
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-cloud-b
  strategy:
  template:
    metadata:
      annotations:
        msePilotCreateAppName: spring-cloud-b
      labels:
        app: spring-cloud-b
    spec:
      containers:
      - env:
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk/jre
        image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-b:0.1-SNAPSHOT
        imagePullPolicy: Always
        name: spring-cloud-b
        ports:
        - containerPort: 8080
        livenessProbe:
          tcpSocket:
            port: 20002
          initialDelaySeconds: 10
          periodSeconds: 30
# B 应用 gray 版本  
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-b-new
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-cloud-b-new
  template:
    metadata:
      annotations:
        alicloud.service.tag: gray
        msePilotCreateAppName: spring-cloud-b
      labels:
        app: spring-cloud-b-new
    spec:
      containers:
      - env:
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk/jre
        image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-b:0.1-SNAPSHOT
        imagePullPolicy: Always
        name: spring-cloud-b-new
        ports:
        - containerPort: 8080
        livenessProbe:
          tcpSocket:
            port: 20002
          initialDelaySeconds: 10
          periodSeconds: 30
# C 应用 base 版本
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-c
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-cloud-c
  template:
    metadata:
      annotations:
        msePilotCreateAppName: spring-cloud-c
      labels:
        app: spring-cloud-c
    spec:
      containers:
      - env:
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk/jre
        image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-c:0.1-SNAPSHOT
        imagePullPolicy: Always
        name: spring-cloud-c
        ports:
        - containerPort: 8080
        livenessProbe:
          tcpSocket:
            port: 20003
          initialDelaySeconds: 10
          periodSeconds: 30
# C 应用 gray 版本
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: spring-cloud-c-new
spec:
  replicas: 2
  selector:
    matchLabels:
      app: spring-cloud-c-new
  template:
    metadata:
      annotations:
        alicloud.service.tag: gray
        msePilotCreateAppName: spring-cloud-c
      labels:
        app: spring-cloud-c-new
    spec:
      containers:
      - env:
        - name: JAVA_HOME
          value: /usr/lib/jvm/java-1.8-openjdk/jre
        image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-c:0.1-SNAPSHOT
        imagePullPolicy: IfNotPresent
        name: spring-cloud-c-new
        ports:
        - containerPort: 8080
        livenessProbe:
          tcpSocket:
            port: 20003
          initialDelaySeconds: 10
          periodSeconds: 30
# Nacos Server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nacos-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nacos-server
  template:
    metadata:
      labels:
        app: nacos-server
    spec:
      containers:
      - env:
        - name: MODE
          value: standalone
        image: nacos/nacos-server:latest
        imagePullPolicy: Always
        name: nacos-server
      dnsPolicy: ClusterFirst
      restartPolicy: Always
# Nacos Server Service 配置
---
apiVersion: v1
kind: Service
metadata:
  name: nacos-server
spec:
  ports:
  - port: 8848
    protocol: TCP
    targetPort: 8848
  selector:
    app: nacos-server
  type: ClusterIP


针对入口应用 A ,配置两个 k8s service, spring-cloud-a-base 对应 A 的 base 版本,spring-cloud-a-gray 对应 A 的 gray 版本。


apiVersion: v1
kind: Service
metadata:
  name: spring-cloud-a-base
spec:
  ports:
    - name: http
      port: 20001
      protocol: TCP
      targetPort: 20001
  selector:
    app: spring-cloud-a
---
apiVersion: v1
kind: Service
metadata:
  name: spring-cloud-a-gray
spec:
  ports:
    - name: http
      port: 20001
      protocol: TCP
      targetPort: 20001
  selector:
    app: spring-cloud-a-new


快速构建全链路灰度能力


  • 泳道为相同版本应用定义的一套隔离环境。只有满足了流控路由规则的请求流量才会路由到对应泳道里的打标应用。一个应用可以属于多个泳道,一个泳道可以包含多个应用,应用和泳道是多对多的关系。


  • 泳道组:泳道的集合。泳道组的作用主要是为了区分不同团队或不同场景。


登录 MSE 治理中心控制台[2],找到 微服务治理中心 > 全链路灰度


3.png

image.gif

可以看到我们需要实现上述描述的能力,我们只需要两个步骤,创建泳道组与创建泳道


创建泳道组


点击创建泳道组按钮,并选择我们泳道组涉及到的后端微服务应用,按照上述 demo 来看就是 A, B, C 三个应用


4.png


创建泳道


全链路灰度页面上方选择创建和泳道组时相同的微服务空间,然后底部单击点击创建第一个分流泳道。需要注意的是 加入全链路流量控制的应用,将不再支持金丝雀发布、标签路由等功能。


5.png


按照产品的 Step 来,我们分别需要起一个泳道名称,配置应用标签,选择泳道关联的标签,去 ACK 控制台配置 Ingress 的路由规则。


创建完成的泳道


查看泳道,分别有两种模式


  • 查看模式

image.gif

6.png


  • 可编辑模式

image.gif

7.png


入口 Ingress 规则


配置入口的 Ingress 规则,访问 www.base.com 路由到 a 应用的 base 版本,访问 www.gray.com 路由到 a 应用的 gray 版本。


apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: spring-cloud-a-base
spec:
  rules:
  - host: www.base.com
    http:
      paths:
      - backend:
          serviceName: spring-cloud-a-base
          servicePort: 20001
        path: /
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: spring-cloud-a-gray
spec:
  rules:
  - host: www.gray.com
    http:
      paths:
      - backend:
          serviceName: spring-cloud-a-gray
          servicePort: 20001
        path: /


验证特征流量路由到目标应用


  1. 结果验证


访问 www.base.com 路由到基线环境


curl -H"Host:www.base.com" http://{ingress-ip}/a
A[172.18.144.155] -> B[172.18.144.120] -> C[172.18.144.79]%


此时,访问 www.gray.com 路由到灰度环境


curl -H"Host:www.gray.com" http://{ingress-ip}/a
Agray[172.18.144.160] -> Bgray[172.18.144.57] -> Cgray[172.18.144.157]%


  1. 查看打标应用的流量监控图。


全链路灰度页面选择目标泳道组。在涉及应用中选择对应的应用,即可出现相应的流量视图


8.png

image.gif

  1. 查看所有应用监控图。


除了查看单个应用的监控图监控图外,我们还可以查看泳道组内所有应用的监控图。通过比对分析所有应用的监控图,可以分析出更多有用信息。


  • 可以看出同一时刻,调用的是哪些应用。
  • 分析流量逃逸问题,判断逃逸对象。


9.png


总结


MSE 服务治理的全链路灰度产品化能力还在不断演进,目前我们支持了 MQ、RPC、可观测等,后续还会支持 XXL-JOB 等更多的场景,目前我们有如何在 MSE 上实现多语言微服务治理[3]、使用 Cloud Toolkit 实现微服务的端云互联[4]、基于 Ingress-nginx 网关实现全链路灰度[5]、基于 MSE 云原生网关实现全链路灰度[6]、基于自建 Spring Cloud Gateway 或 Zuul 网关实现全链路灰度[7]、基于消息队列 RocketMQ 版实现全链路灰度[8]、通过 Jenkins 构建 CI/CD 实现金丝雀发布[9]、微服务敏捷开发最佳实践[10]等全链路灰度相关的完整解决方案,随着用户场景与实践的增多,我们的解决方案还会不断迭代与丰富。


典型案例


来电科技


MSE 服务治理帮助我们系统以很低的成本无侵入的方式快速实现了全链路灰度能力,进一步提升了我们系统的稳定性,让我们新需求的迭代上线更加地安心。
-- 来电科技架构师 汤长征


来电科技自 2014 年起开始进入共享充电领域,定义并开创了行业,属于行业内最早的共享充电企业。主要业务覆盖充电宝自助租赁、定制商场导航机开发、广告展示设备及广告传播等服务。来电科技拥有业内立体化产品线,大中小机柜以及桌面型,目前全国超过 90%的城市实现业务服务落地,注册用户超 2 亿人,实现全场景用户需求。


全链路灰度落地


来电的业务架构如下,最上层是移动端等用户界面,自建的 Nginx 网关作为接入层,服务层就是各种服务,使用的是 Spring Cloud 与 Dubbo 作为服务框架。


10.png


来电科技全链路灰度落地的架构如下:

image.gif

11.png


在 Nginx 层配置流量分流的配置,10% 的流量进入灰度环境,90% 的流量进入未打标即线上正式环境,然后经过灰度环境的流量会自动被 MSE 染上对应环境的颜色,从而进行全链路的灰度路由,保证流量在灰度环境中闭环,如果没有灰度环境的机器,比如支付中心只有线上的机器,那么流量会走线上环境,当我们数据中心有存在灰度环境的机器,那么灰度流量还会重新回到数据中心的灰度环境中。




MSE 的全链路灰度能力随着客户场景的深入而不断扩展与迭代,只有经过客户打磨的产品才会愈发历久弥新,欢迎大家尝鲜体验。


相关链接


[1] 容器服务控制台

https://cs.console.aliyun.com/#/authorize


[2] MSE 治理中心控制台

https://mse.console.aliyun.com/?spm=a2c4g.11186623.2.13.f90a6a60WiEx0N#/auth


[3] 如何在 MSE 上实现多语言微服务治理

https://help.aliyun.com/document_detail/184289.html


[4] 使用 Cloud Toolkit 实现微服务的端云互联

https://help.aliyun.com/document_detail/196920.html


[5] 基于 Ingress-nginx 网关实现全链路灰度

https://help.aliyun.com/document_detail/347790.html


[6] 基于 MSE 云原生网关实现全链路灰度

https://help.aliyun.com/document_detail/359851.html


[7] 基于自建 Spring Cloud Gateway 或 Zuul 网关实现全链路灰度

https://help.aliyun.com/document_detail/359858.html


[8] 基于消息队列 RocketMQ 版实现全链路灰度

https://help.aliyun.com/document_detail/397318.html


[9] 通过 Jenkins 构建 CI/CD 实现金丝雀发布

https://help.aliyun.com/document_detail/384436.html


[10] 微服务敏捷开发最佳实践

https://help.aliyun.com/document_detail/397319.html


点击文末“此处”,了解更多详情~

相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
消息中间件 存储 Kubernetes
Helm方式部署 zookeeper+kafka 集群 ——2023.05
Helm方式部署 zookeeper+kafka 集群 ——2023.05
1082 0
|
4月前
|
运维 Cloud Native 应用服务中间件
阿里云微服务引擎 MSE 及 API 网关 2025 年 5 月产品动态
阿里云微服务引擎 MSE 面向业界主流开源微服务项目, 提供注册配置中心和分布式协调(原生支持 Nacos/ZooKeeper/Eureka )、云原生网关(原生支持Higress/Nginx/Envoy,遵循Ingress标准)、微服务治理(原生支持 Spring Cloud/Dubbo/Sentinel,遵循 OpenSergo 服务治理规范)能力。API 网关 (API Gateway),提供 APl 托管服务,覆盖设计、开发、测试、发布、售卖、运维监测、安全管控、下线等 API 生命周期阶段。帮助您快速构建以 API 为核心的系统架构.满足新技术引入、系统集成、业务中台等诸多场景需要
|
Kubernetes Cloud Native Dubbo
全链路灰度的挑战、实现思路与解决方案
全链路灰度的挑战、实现思路与解决方案
1435 99
|
JSON 监控 安全
分享一例有意思的灰度设计缺陷,浅谈灰度方案的设计
灰度很重要,灰度的策略也需要结合实际情况进行灵活的调整,本文跟大家分享了一个前些时间发现的灰度设计bug。
|
测试技术
[googletest] --- 简易使用教程
[googletest] --- 简易使用教程
834 0
如何从多个文件夹里各提取相应数量的文件放一起到新文件夹中形成多文件夹组合
该文介绍了一个工具的使用方法,通过它可以从多个文件夹中批量提取并合并文件。文中提供了两个下载链接(度娘网盘和蓝奏云)并附有提取码。工具主要用于平均分配文件到指定文件夹,例如将100张图片平均放入50个文件夹,每个文件夹2张。操作步骤包括创建目标文件夹、添加源文件夹路径、启用“平均复制”选项,然后执行任务。最后,展示了操作完成后文件夹内的正确分布情况。
514 10
|
设计模式 数据可视化 关系型数据库
设计之美-揭秘设计模式、原则与UML的魔法
设计模式、设计原则和UML是软件工程设计中的核心要素。设计模式为常见问题提供经验证的解决方案,复用性高且提升开发效率。设计原则指导我们创建灵活、可维护和可扩展的系统,确保代码质量和长期可维护性。UML(统一建模语言)则是一种强大的可视化工具,用于描述、构建和文档化软件系统的结构和行为。它帮助开发者更清晰地理解系统架构和组件间关系。综合应用设计模式、设计原则和UML,能够显著提高软件开发的效率和质量,减少维护成本,为复杂系统的设计和实施提供有力支持。
258 0
设计之美-揭秘设计模式、原则与UML的魔法
|
JavaScript 前端开发 Java
博客管理系统|基于SpringBoot+Vue+ElementUI个人博客系统的设计与实现
博客管理系统|基于SpringBoot+Vue+ElementUI个人博客系统的设计与实现
593 0
|
存储 安全 算法
C# 泛型:类型参数化的强大工具
【1月更文挑战第7天】本文将深入探讨C#语言中的泛型编程,包括泛型的定义、用途、优势以及实际应用。通过类型参数化,泛型允许开发者编写更加灵活且可重用的代码,同时提高程序的类型安全性和性能。本文将通过示例代码和详细解释,帮助读者更好地理解泛型在C#中的重要性和实用性。
|
存储 Python
Python案例分析|文本相似度比较分析
本案例通过设计和实现有关文本相似度比较的类Vector和Sketch,帮助大家进一步掌握设计Python类来解决实际问题的能力。
301 0
Python案例分析|文本相似度比较分析