作者:泮圣伟(十眠)
概要
全链路灰度是微服务最外围的性能之一,也始终是云上客户在微服务化深刻过程中必须具备的性能。全链路灰度因为波及到的技术、场景泛滥,如果云上企业一一本人实现,须要破费大量人力老本对其进行扩大与运维。
波及到的技术畛域
- 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) 灰度流量携带灰度标往上游传递,造成灰度专属环境流量泳道,无灰度环境利用会默认抉择未打标的基线环境。
- 端到端的稳固基线环境
未打标的利用属于基线稳固版本的利用,即稳固的线上环境。当咱们将公布对应的灰度版本代码,而后能够配置规定定向引入特定的线上流量,管制灰度代码的危险。
- 流量一键动静切流
流量规定定制后,可依据需要进行一键停启,增删改查,实时失效。灰度引流更便捷。
- 可观测能力
具备泳道级别的单利用可观测能力
同时具备全链路利用的可观测能力,能够从全局视角察看流量是否存在逃逸状况。灰没灰到,高深莫测。
- 低成本接入,基于 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] 。
- 在左侧导航栏抉择市场 > 利用目录。
- 在利用目录页面搜寻框中输出 ack-ingress-nginx,单击图标,而后单击组件。
- 在详情 页面抉择组件的 命名空间 为 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] ,找到 微服务治理核心 > 全链路灰度
能够看到咱们须要实现上述形容的能力,咱们只须要两个步骤,创立泳道组与创立泳道
创立泳道组
点击创立泳道组按钮,并抉择咱们泳道组波及到的后端微服务利用,依照上述 demo 来看就是 A, B, C 三个利用
创立泳道
在全链路灰度 页面上方抉择创立和泳道组时雷同的微服务空间,而后底部单击 点击创立第一个分流泳道。须要留神的是 退出全链路流量管制的利用,将不再反对金丝雀公布、标签路由等性能。
依照产品的 Step 来,咱们别离须要起一个泳道名称,配置利用标签,抉择泳道关联的标签,去 ACK 控制台配置 Ingress 的路由规定。
创立实现的泳道
查看泳道,别离有两种模式
- 查看模式
- 可编辑模式
入口 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: /
验证特色流量路由到指标利用
- 后果验证
拜访 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]%
- 查看打标利用的流量监控图。
在全链路灰度页面抉择指标泳道组。在波及利用中抉择对应的利用,即可呈现相应的流量视图
- 查看所有利用监控图。
除了查看单个利用的监控图监控图外,咱们还能够查看泳道组内所有利用的监控图。通过比对剖析所有利用的监控图,能够剖析出更多有用信息。
- 能够看出同一时刻,调用的是哪些利用。
- 剖析流量逃逸问题,判断逃逸对象。
总结
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 作为服务框架。
复电科技全链路灰度落地的架构如下:
在 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
点击文末“此处”,理解更多详情~