共计 11848 个字符,预计需要花费 30 分钟才能阅读完成。
简介:本文将以上次介绍过的《如何用 20 分钟就能取得同款企业级全链路灰度能力?》中的场景为根底,来进一步介绍音讯场景的全链路灰度。
作者:亦盏
之前的系列文章中,咱们曾经通过全链路金丝雀公布这个性能来介绍了 MSE 对于全链路流量管制的场景,咱们曾经理解了 Spring Cloud 和 Dubbo 这一类 RPC 调用的全链路灰度应该如何实现,然而没有波及到音讯这类异步场景下的流量管制,明天咱们将以上次介绍过的《如何用 20 分钟就能取得同款企业级全链路灰度能力?》中的场景为根底,来进一步介绍音讯场景的全链路灰度。
尽管绝大多数业务场景下对于音讯的灰度的要求并不像 RPC 的要求得这么严格,然而在以下两个场景下,还是会对音讯的全链路有肯定的诉求的。
1、第一种场景是在音讯生产时,可能会产生新的 RPC 调用,如果没有在音讯这一环去遵循之前设定好的全链路流量管制的规定,会导致通过音讯产生的这部分流量“逃逸”,从而导致全链路灰度的规定受到毁坏,导致呈现不合乎预期的状况。
为了防止出现这个状况,咱们须要在生产时候将音讯里原来的流量标还原,并在 RPC 调用的时候遵循原来的规定。咱们通过架构图来详细描述一下,满足这个逻辑之后,调用链路是怎么的,从下图中咱们能够看到,灰度和基线环境生产进去的音讯,尽管在音讯推送的时候是随机的,然而在生产过程中,产生的新的 RPC 调用,还是可能回到流量原来所属的环境。
2、第二种场景须要更加严格的音讯灰度隔离。比方当音讯的生产逻辑进行了批改时,这时候心愿通过小流量的形式来验证新的音讯生产逻辑的正确性,要严格地要求灰度的音讯只能被推送给灰度的音讯消费者。
明天咱们就来实操一下第二种场景音讯的全链路灰度,目前 MSE 仅反对 RocketMQ 音讯的灰度。若您应用的是开源版 RocketMQ,那么版本须要在 4.5.0 及以上,若您应用的是阿里云商业版 RocketMQ,那么须要应用铂金版,且 Ons Client 版本在 1.8.0.Final 及以上。如果只是想应用第一种场景,只须要给 B 利用开启全链路灰度的性能即可,不须要做额定的音讯灰度相干的配置。
在这次最佳实际的操作中,咱们是将利用部署在阿里云容器服务 Kubernetes 版本,即 ACK 集群来演示,然而事实上,音讯灰度对于利用的部署模式是没有限制性要求的,您能够参考 MSE 帮忙文档,找到本人所应用的部署模式对应的接入形式,也能应用音讯全链路灰度。
前提条件
开明 MSE 专业版,请参见开明 MSE 微服务治理专业版[1]。
创立 ACK 集群,请参见创立 Kubernetes 集群[2]。
操作步骤
步骤一:接入 MSE 微服务治理
1、装置 mse-ack-pilot
- 登录容器服务控制台[3]。
- 在左侧导航栏单击市场 > 利用目录。
- 在利用目录页面点击阿里云利用,抉择微服务,并单击 ack-mse-pilot。
- 在 ack-mse-pilot 页面右侧集群列表中抉择集群,而后单击创立。
装置 MSE 微服务治理组件大概须要 2 分钟,请急躁期待。
创立胜利后,会主动跳转到指标集群的 Helm 页面,查看装置后果。如果呈现以下页面,展现相干资源,则阐明装置胜利。
2、为 ACK 命名空间中的利用开启 MSE 微服务治理
登录 MSE 治理核心控制台[4],如果您尚未开明 MSE 微服务治理,请依据提醒开明。
在左侧导航栏抉择微服务治理核心 > Kubernetes 集群列表。
在 Kubernetes 集群列表页面搜寻框列表中抉择集群名称或集群 ID,而后输出相应的关键字,单击搜寻图标。
单击指标集群操作列的治理。
在集群详情页面命名空间列表区域,单击指标命名空间操作列下的开启微服务治理。
在开启微服务治理对话框中单击确认。
步骤二:还原线上场景
首先,咱们将别离部署 spring-cloud-zuul、spring-cloud-a、spring-cloud-b、spring-cloud-c 这四个业务利用,以及注册核心 Nacos Server 和音讯服务 RocketMQ Server,模拟出一个实在的调用链路。
Demo 利用的结构图下图,利用之间的调用,既蕴含了 Spring Cloud 的调用,也蕴含了 Dubbo 的调用,笼罩了以后市面上最罕用的两种微服务框架。其中 C 利用会生产出 RocketMQ 音讯,由 A 利用进行生产,A 在生产音讯时,也会发动新的调用。这些利用都是最简略的 Spring Cloud、Dubbo 和 RocketMQ 的规范用法,您也能够间接在 https://github.com/aliyun/ali… 我的项目上查看源码。
部署之前,简略介绍一下这个调用链路
spring-cloud-zuul 利用在收到“/A/dubbo”的申请时,会把申请转发给 spring-cloud-a,而后 spring-cloud-a 通过 dubbo 协定去拜访 spring-cloud-b,spring-cloud-b 也通过 dubbo 协定去拜访 spring-cloud-c,spring-cloud-c 在收到申请后,会生产一个音讯,并返回本人的环境标签和 ip。这些生产进去的音讯会由 spring-cloud-a 利用生产,spring-cloud-a 利用在生产音讯的时候,会通过 spring cloud 去调用 B,B 进而通过 spring cloud 去调用 C,并且将后果输入到本人的日志中。
当咱们调用 /A/dubbo 的时候
返回值是这样 A[10.25.0.32] -> B[10.25.0.152] -> C[10.25.0.30]
同时,A 利用在接管到音讯之后,输入的日志如下
2021-12-28 10:58:50.301 INFO 1 --- [essageThread_15] c.a.mse.demo.service.MqConsumer : topic:TEST_MQ,producer:C[10.25.0.30],invoke result:A[10.25.0.32] -> B[10.25.0.152] -> C[10.25.0.30]
相熟了调用链路之后,咱们持续部署利用,您能够应用 kubectl 或者间接应用 ACK 控制台来部署利用。部署所应用的 yaml 文件如下,您同样能够间接在 https://github.com/aliyun/ali… 上获取对应的源码。
# 部署 Nacos Server
apiVersion: apps/v1
kind: Deployment
metadata:
name: nacos-server
spec:
selector:
matchLabels:
app: nacos-server
template:
metadata:
annotations:
labels:
app: nacos-server
spec:
containers:
- env:
- name: MODE
value: "standalone"
image: registry.cn-shanghai.aliyuncs.com/yizhan/nacos-server:latest
imagePullPolicy: IfNotPresent
name: nacos-server
ports:
- containerPort: 8848
---
apiVersion: v1
kind: Service
metadata:
name: nacos-server
spec:
type: ClusterIP
selector:
app: nacos-server
ports:
- name: http
port: 8848
targetPort: 8848
# 部署业务利用
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-zuul
spec:
selector:
matchLabels:
app: spring-cloud-zuul
template:
metadata:
annotations:
msePilotCreateAppName: spring-cloud-zuul
labels:
app: spring-cloud-zuul
spec:
containers:
- env:
- name: JAVA_HOME
value: /usr/lib/jvm/java-1.8-openjdk/jre
- name: enable.mq.invoke
value: 'true'
image: registry.cn-shanghai.aliyuncs.com/yizhan/spring-cloud-zuul:1.0.0
imagePullPolicy: Always
name: spring-cloud-zuul
ports:
- containerPort: 20000
---
apiVersion: v1
kind: Service
metadata:
annotations:
service.beta.kubernetes.io/alibaba-cloud-loadbalancer-spec: slb.s1.small
service.beta.kubernetes.io/alicloud-loadbalancer-address-type: internet
name: zuul-slb
spec:
ports:
- port: 80
protocol: TCP
targetPort: 20000
selector:
app: spring-cloud-zuul
type: LoadBalancer
status:
loadBalancer: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-a
spec:
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:1.0.0
imagePullPolicy: Always
name: spring-cloud-a
ports:
- containerPort: 20001
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 10
periodSeconds: 30
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-b
spec:
selector:
matchLabels:
app: spring-cloud-b
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:1.0.0
imagePullPolicy: Always
name: spring-cloud-b
ports:
- containerPort: 20002
livenessProbe:
tcpSocket:
port: 20002
initialDelaySeconds: 10
periodSeconds: 30
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c
spec:
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:1.0.0
imagePullPolicy: Always
name: spring-cloud-c
ports:
- containerPort: 20003
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 10
periodSeconds: 30
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rockectmq-broker
spec:
selector:
matchLabels:
app: rockectmq-broker
template:
metadata:
labels:
app: rockectmq-broker
spec:
containers:
- command:
- sh
- mqbroker
- '-n'
- 'mqnamesrv:9876'
- '-c /home/rocketmq/rocketmq-4.5.0/conf/broker.conf'
env:
- name: ROCKETMQ_HOME
value: /home/rocketmq/rocketmq-4.5.0
image: registry.cn-shanghai.aliyuncs.com/yizhan/rocketmq:4.5.0
imagePullPolicy: Always
name: rockectmq-broker
ports:
- containerPort: 9876
protocol: TCP
- containerPort: 10911
protocol: TCP
- containerPort: 10912
protocol: TCP
- containerPort: 10909
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: rocketmq-name-server
spec:
selector:
matchLabels:
app: rocketmq-name-server
template:
metadata:
labels:
app: rocketmq-name-server
spec:
containers:
- command:
- sh
- mqnamesrv
env:
- name: ROCKETMQ_HOME
value: /home/rocketmq/rocketmq-4.5.0
image: registry.cn-shanghai.aliyuncs.com/yizhan/rocketmq:4.5.0
imagePullPolicy: Always
name: rocketmq-name-server
ports:
- containerPort: 9876
protocol: TCP
- containerPort: 10911
protocol: TCP
- containerPort: 10912
protocol: TCP
- containerPort: 10909
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: mqnamesrv
spec:
type: ClusterIP
selector:
app: rocketmq-name-server
ports:
- name: mqnamesrv-9876-9876
port: 9876
targetPort: 9876
装置胜利后,示例如下:➜ ~ kubectl get svc,deploy
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 192.168.0.1 <none> 443/TCP 7d
service/mqnamesrv ClusterIP 192.168.213.38 <none> 9876/TCP 47h
service/nacos-server ClusterIP 192.168.24.189 <none> 8848/TCP 47h
service/zuul-slb LoadBalancer 192.168.189.111 123.56.253.4 80:30260/TCP 47h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nacos-server 1/1 1 1 4m
deployment.apps/rockectmq-broker 1/1 1 1 4m
deployment.apps/rocketmq-name-server 1/1 1 1 5m
deployment.apps/spring-cloud-a 1/1 1 1 5m
deployment.apps/spring-cloud-b 1/1 1 1 5m
deployment.apps/spring-cloud-c 1/1 1 1 5m
deployment.apps/spring-cloud-zuul 1/1 1 1 5m
同时这里咱们能够通过 zuul-slb 来验证一下方才所说的调用链路
➜ ~ curl http://123.56.253.4/A/dubbo
A[10.25.0.32] -> B[10.25.0.152] -> C[10.25.0.30]
步骤三:开启音讯灰度性能
当初依据控制台的提醒,在音讯的生产者 spring-cloud-c 和音讯的消费者 spring-cloud-a 都开启音讯的灰度。咱们间接通过 MSE 的控制台开启,点击进入利用的详情页,抉择“音讯灰度”标签。
能够看到,在未打标环境疏忽的标签中,咱们输出了 gray,这里意味着,带着 gray 环境标的音讯,只能由 spring-cloud-a-gray 生产,不能由 spring-cloud-a 来生产。
1、这里须要额定阐明一下,因为思考到理论场景中,spring-cloud-c 利用和 spring-cloud-a 利用的所有者可能不是同一个人,不肯定可能做到两者同时进行灰度公布同步的操作,所以在音讯的灰度中,未打标环境默认的行为是生产所有音讯。这样 spring-cloud-c 在进行灰度公布的时候,能够不须要强制 spring-cloud-a 利用也肯定要同时灰度公布。
2、咱们把未打标环境消费行为的选择权交给 spring-cloud-a 的所有者,如果须要实现未打标环境不生产 c-gray 生产进去的音讯,只须要在控制台进行配置即可,配置之后实时失效。
应用此性能您无需批改利用的代码和配置。
音讯的生产者和音讯的消费者,须要同时开启音讯灰度,音讯的灰度性能能力失效。
音讯类型目前只反对 RocketMQ,蕴含开源版本和阿里云商业版。
如果您应用开源 RocketMQ,则 RocketMQ Server 和 RocketMQ Client 都须要应用 4.5.0 及以上版本。
如果您应用阿里云 RocketMQ,须要应用铂金版,且 Ons Client 应用 1.8.0.Final 及以上版本。
开启音讯灰度后,MSE 会批改音讯的 Consumer Group。例如原来的 Consumer Group 为 group1,环境标签为 gray,开启音讯灰度后,则 group 会被批改成 group1_gray,如果您应用的是阿里云 RocketMQ,请提前创立好 group。
默认应用 SQL92 的过滤形式,如果您应用的开源 RocketMQ,须要在服务端开启此性能(即在 broker.conf 中配置 enablePropertyFilter=true)。
默认状况下,未打标节点将生产所有环境的音讯,若须要指定 未打标环节点 不生产 某个标签环境生产进去的音讯,请配置“未打标环境疏忽的标签”,批改此配置后动静失效,无需重启利用。
步骤四:重启节点,部署新版本利用,并引入流量进行验证
首先,因为开启和敞开利用的音讯灰度性能后都须要重启节点能力失效,所以首先咱们须要重启一下 spring-cloud-a 和 spring-cloud-c 利用,重启的形式能够在管制台上抉择重新部署,或者间接应用 kubectl 命令删除现有的 pod。
而后,持续应用 yaml 文件的形式在 Kubernetes 集群中部署新版本的 spring-cloud-a-gray、spring-cloud-b-gray 和 spring-cloud-c-gray
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-a-gray
spec:
selector:
matchLabels:
app: spring-cloud-a-gray
template:
metadata:
annotations:
alicloud.service.tag: gray
msePilotCreateAppName: spring-cloud-a
labels:
app: spring-cloud-a-gray
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:1.0.0
imagePullPolicy: Always
name: spring-cloud-a-gray
ports:
- containerPort: 20001
livenessProbe:
tcpSocket:
port: 20001
initialDelaySeconds: 10
periodSeconds: 30
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-b-gray
spec:
selector:
matchLabels:
app: spring-cloud-b-gray
template:
metadata:
annotations:
alicloud.service.tag: gray
msePilotCreateAppName: spring-cloud-b
labels:
app: spring-cloud-b-gray
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:1.0.0
imagePullPolicy: Always
name: spring-cloud-b-gray
ports:
- containerPort: 20002
livenessProbe:
tcpSocket:
port: 20002
initialDelaySeconds: 10
periodSeconds: 30
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-cloud-c-gray
spec:
selector:
matchLabels:
app: spring-cloud-c-gray
template:
metadata:
annotations:
alicloud.service.tag: gray
msePilotCreateAppName: spring-cloud-c
labels:
app: spring-cloud-c-gray
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:1.0.0
imagePullPolicy: Always
name: spring-cloud-c-gray
ports:
- containerPort: 20003
livenessProbe:
tcpSocket:
port: 20003
initialDelaySeconds: 10
periodSeconds: 30
部署实现之后,咱们引入流量,并进行验证
登录 MSE 治理核心控制台[4],抉择利用列表。
单击利用 spring-cloud-a 利用详情菜单,此时能够看到,所有的流量申请都是去往 spring-cloud-a 利用未打标的版本,即稳固版本。
点击页面下方的 标签路由中的增加按钮,为 spring-cloud-a 利用的 gray 版本设置灰度规定。
发动流量调用,咱们通过 zuul-slb,别离发动流量调用,并查看灰度的状况。
咱们通过 spring-cloud-a 和 spring-cloud-a-gray 的日志去查看音讯生产的状况。能够看到,音讯的灰度性能曾经失效,spring-cloud-a-gray 这个环境,只会生产带有 gray 标的音讯,spring-cloud-a 这个环境,只会生产未打标的流量生产进去的音讯。
在截图中咱们能够看见,spring-cloud-a-gray 环境输入的日志 topic:TEST_MQ, producer: Cgray [10.25.0.102] , invoke result: Agray[10.25.0.101] -> Bgray[10.25.0.25] -> Cgray[10.25.0.102],spring-cloud-a-gray 只会生产 Cgray 生产进去的音讯,而且生产音讯过程中发动的 Spring Cloud 调用,后果也是 Agray[10.25.0.101] -> Bgray[10.25.0.25] -> Cgray[10.25.0.102],即在灰度环境闭环。
而 spring-cloud-a 这个环境,输入的日志为 topic:TEST_MQ,producer:C[10.25.0.157],invoke result:A[10.25.0.100] -> B[10.25.0.152] -> C[10.25.0.157],只会生产 C 的基线环境生产进去的音讯,且在这个过程中发动的 Spring Cloud 调用,也是在基线环境闭环。
步骤五:调整音讯的标签过滤规定,并进行验证
因为思考到理论场景中,spring-cloud-c 利用和 spring-cloud-a 利用的所有者可能不是同一个人,不肯定可能做到两者同时进行灰度公布同步的操作,所以在音讯的灰度中,未打标环境默认的行为是生产所有音讯。这样 spring-cloud-c 在进行灰度公布的时候,能够不须要强制 spring-cloud-a 利用也肯定要同时灰度公布,且应用雷同的环境标。
spring-cloud-a 在生产时候,未打标环境的行为的选择权是交给 spring-cloud-a 的所有者,如果须要实现未打标环境不生产 c-gray 生产进去的音讯,只须要在控制台进行配置即可,配置之后实时失效。
调整 spring-cloud-a 未打标环境的过滤规定。比方这里咱们要抉择未打标环境不再生产 gray 环境生产进去的音讯,只须要在“未打标环境疏忽的标签”外面抉择 gray,而后点击确定即可。
调整规定之后,规定是能够动静地失效,不须要进行重启的操作,咱们间接查看 spring-cloud-a 的日志,验证规定调整失效。
从这个日志中,咱们能够看到,此时基线环境能够同时生产 gray 和 基线环境生产进去的音讯,而且在生产对应环境音讯时产生的 Spring Cloud 调用别离路由到 gray 和 基线环境中。
操作总结
全链路音讯灰度的整个过程是不须要批改任何代码和配置的。
目前仅反对 RocketMQ,Client 版本须要在 4.5.0 之后的版本。RocketMQ Server 端须要反对 SQL92 规定过滤,即开源 RocketMQ 须要配置 enablePropertyFilter=true,阿里云 RocketMQ 须要应用铂金版。
开启音讯灰度后,MSE Agent 会批改音讯消费者的 group,如原来的生产 group 为 group1,环境标签为 gray,则 group 会被批改成 group1_gray,如果应用的是阿里云 RocketMQ,须要提前创立好批改后的 group。
开启和敞开音讯灰度后,利用须要重启能力失效;批改未打标环境疏忽的标签性能能够动静失效,不须要重启。
相干链接
[1] MSE 微服务治理专业版:
https://help.aliyun.com/docum…
[2] Kubernetes 集群:
https://help.aliyun.com/docum…
[3] 容器服务控制台:
https://cs.console.aliyun.com/
[4] MSE 治理核心控制台
https://mse.console.aliyun.co…
原文链接
本文为阿里云原创内容,未经容许不得转载。