基于阿里云服务网格流量泳道的全链路流量管理(三):无侵入式的宽松模式泳道

作者:尹航

在前文《基于阿里云服务网格流量泳道的全链路流量管理(一):严格模式流量泳道》、《基于阿里云服务网格流量泳道的全链路流量管理(二):宽松模式流量泳道》中,我们介绍了流量泳道的概念、使用流量泳道进行全链路灰度管理的方案,以及阿里云服务网格 ASM 提供的严格模式与宽松模式的流量泳道。在本文中,我们将介绍一种基于 OpenTelemetry 自动插装方案实现的宽松模式流量泳道场景,无需任何业务代码改造即可为运行在 Kubernetes 集群中的云原生应用实现灵活的全链路灰度管理能力。

概述

流量泳道是将一个云原生应用中的多个服务根据服务版本(或其他特征)隔离成的多个独立的运行环境。

在严格模式下,每条流量泳道中包含应用的调用链路上的全部服务,对于应用程序则没有任何要求。

而在宽松模式下,您只需要确保创建一条包含调用链路中所有服务的泳道:基线泳道。其它泳道可以不包含调用链路上的全部服务。当一个泳道中的服务进行相互调用时,若目标服务在当前泳道中不存在,则请求将被转发到基线泳道中的相同服务,并在请求目标存在当前泳道中存在时将请求重新转发回当前泳道。宽松模式的流量泳道虽然可以实现灵活的全链路灰度,但要求应用程序必须包含一个能够在整条调用链路中透传的请求头(链路透传请求头)。

阿里云服务网格 ASM 已经提供一种基于 baggage 透传的全新宽松模式流量泳道方案,能够在不改造业务代码的情况下,实现泳道服务的灵活灰度。

背景介绍

OpenTelemetry 是云原生计算基金会(Cloud Native Computing Foundation, CNCF)的一个项目,与其他 CNCF 项目如 Kubernetes、Prometheus 和 Envoy 等紧密相连,共同构建了云原生技术生态系统的基础。由于其提供的丰富功能和广泛适用性,OpenTelemetry 在业内已经确立了其领导地位,越来越多的企业和开发者采用它作为构建和维护可观测性平台的核心组件。

baggage 是由 OpenTelemetry 制定并推动的、在分布式系统调用链路中传递链路上下文信息的标准。它具体表现为一个名为 baggage 的请求头,其内部包含了以键值对形式存储的链路上下文信息,例如:

baggage: userId=alice,serverNode=DF%2028,isProduction=false

您可以使用 OpenTelemetry 提供的 SDK,在服务调用链路中传递 baggage 请求头、进而在整条服务链路上传递自定义的上下文信息。当服务部署在 Kubernentes 集群中时,则可以通过 OpenTelemetry Operator 的自动插装来为服务提供 baggage 透传能力、而无需修改业务代码。有关 baggage 的详细信息,可以参考 baggage [ 1]

基于 baggage 的透传,阿里云服务网格 ASM 提供了一种无需修改代码即可实现的宽松模式流量泳道,并针对流量泳道的引流策略进行了增强,支持基于流量权重策略对不同的泳道进行引流。本文将首先使用 OpenTelemetry 自动插装来为服务引用透传 baggage 请求头的能力,接下来创建宽松模式下的三条泳道,并基于流量权重策略对不同的泳道进行引流。

演示:实现服务 baggage 透传与宽松模式流量泳道

前提条件

  • 已创建 ASM 企业版或旗舰版实例,且版本为 1.21.6.54 及以上。具体操作,请参见创建 ASM 实例 [ 2]
  • 已添加集群到 ASM 实例。具体操作,请参见添加集群到 ASM 实例 [ 3]
  • 已创建名称为 ingressgateway 的 ASM 网关。具体操作,请参见创建入口网关服务 [ 4]
  • 已创建名称为 ingressgateway 且命名空间为 istio-system 的网关规则。具体操作,请参见管理网关规则 [ 5]
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:name: ingressgatewaynamespace: istio-system
spec:selector:istio: ingressgatewayservers:- port:number: 80name: httpprotocol: HTTPhosts:- '*'

步骤一:配置服务透传 baggage 上下文

本节主要展示如何通过 OpenTelemetry Operator 自动插装的方法,为 Kubernetes 集群中的服务添加 baggage 透传能力。

  1. 部署 OpenTelemetry Operator。

a. 通过 kubectl 连接到 ASM 实例添加的 Kubernetes 集群。执行以下命令,创建 opentelemetry-operator-system 命名空间。

kubectl create namespace opentelemetry-operator-system

b. 执行以下命令,使用 Helm 在 opentelemetry-operator-system 命名空间下安装 OpenTelemetry Operator。(如果尚未安装 Helm,可以参考安装 Helm 来安装 Helm 命令行工具。)

helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm install \--namespace=opentelemetry-operator-system \--version=0.46.0 \--set admissionWebhooks.certManager.enabled=false \--set admissionWebhooks.certManager.autoGenerateCert=true \--set manager.image.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-operator" \--set manager.image.tag="0.92.1" \--set kubeRBACProxy.image.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/kube-rbac-proxy" \--set kubeRBACProxy.image.tag="v0.13.1" \--set manager.collectorImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-collector" \--set manager.collectorImage.tag="0.97.0" \--set manager.opampBridgeImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/operator-opamp-bridge" \--set manager.opampBridgeImage.tag="0.97.0" \--set manager.targetAllocatorImage.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/target-allocator" \--set manager.targetAllocatorImage.tag="0.97.0" \--set manager.autoInstrumentationImage.java.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-java" \--set manager.autoInstrumentationImage.java.tag="1.32.1" \--set manager.autoInstrumentationImage.nodejs.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-nodejs" \--set manager.autoInstrumentationImage.nodejs.tag="0.49.1" \--set manager.autoInstrumentationImage.python.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-python" \--set manager.autoInstrumentationImage.python.tag="0.44b0" \--set manager.autoInstrumentationImage.dotnet.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/autoinstrumentation-dotnet" \--set manager.autoInstrumentationImage.dotnet.tag="1.2.0" \--set manager.autoInstrumentationImage.go.repository="registry-cn-hangzhou.ack.aliyuncs.com/acs/opentelemetry-go-instrumentation" \--set manager.autoInstrumentationImage.go.tag="v0.10.1.alpha-2-aliyun" \opentelemetry-operator open-telemetry/opentelemetry-operator

c. 执行以下命令,检查 opentelemetry-operator 是否正常运行。

kubectl get pod -n opentelemetry-operator-system

预期输出:

NAME READY   STATUS    RESTARTS   AGE
opentelemetry-operator-854fb558b5-pvllj   2/2     Running   0          1m
  1. 配置自动插装(auto-instrumentation)。

a. 使用以下内容,创建 instrumentation.yaml 文件。

apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:name: demo-instrumentation
spec:propagators:- baggagesampler:type: parentbased_traceidratioargument: "1"

b. 执行以下命令,在 default 命名空间下声明自动插装。

kubectl apply -f instrumentation.yaml

🔔 说明: 对于 OpenTelemetry 框架来说,其最佳实践还包括部署 OpenTelemetry Collector 以收集可观测数据。由于本文主要演示 OpenTelemetry 自动插装实现的 baggage 链路透传,因此没有包含部署 OpenTelemetry Collector 的步骤。

步骤二:部署示例服务

  1. 为 default 命名空间启用 Siedcar 网格代理自动注入。具体操作,请参见开启  Sidecar 自动注入 [ 6]

关于自动注入的更多信息,请参见配置 Sidecar 注入策略。

  1. 使用以下内容,创建 mock.yaml 文件。
apiVersion: v1
kind: Service
metadata:name: mockalabels:app: mockaservice: mocka
spec:ports:- port: 8000name: httpselector:app: mocka
---
apiVersion: apps/v1
kind: Deployment
metadata:name: mocka-v1labels:app: mockaversion: v1
spec:replicas: 1selector:matchLabels:app: mockaversion: v1ASM_TRAFFIC_TAG: v1template:metadata:labels:app: mockaversion: v1ASM_TRAFFIC_TAG: v1annotations:instrumentation.opentelemetry.io/inject-java: "true"instrumentation.opentelemetry.io/container-names: "default"spec:containers:- name: defaultimage: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-javaimagePullPolicy: IfNotPresentenv:- name: versionvalue: v1- name: appvalue: mocka- name: upstream_urlvalue: "http://mockb:8000/"ports:- containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:name: mockblabels:app: mockbservice: mockb
spec:ports:- port: 8000name: httpselector:app: mockb
---
apiVersion: apps/v1
kind: Deployment
metadata:name: mockb-v1labels:app: mockbversion: v1
spec:replicas: 1selector:matchLabels:app: mockbversion: v1ASM_TRAFFIC_TAG: v1template:metadata:labels:app: mockbversion: v1ASM_TRAFFIC_TAG: v1annotations:instrumentation.opentelemetry.io/inject-java: "true"instrumentation.opentelemetry.io/container-names: "default"spec:containers:- name: defaultimage: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-javaimagePullPolicy: IfNotPresentenv:- name: versionvalue: v1- name: appvalue: mockb- name: upstream_urlvalue: "http://mockc:8000/"ports:- containerPort: 8000---
apiVersion: v1
kind: Service
metadata:name: mockclabels:app: mockcservice: mockc
spec:ports:- port: 8000name: httpselector:app: mockc
---
apiVersion: apps/v1
kind: Deployment
metadata:name: mockc-v1labels:app: mockcversion: v1
spec:replicas: 1selector:matchLabels:app: mockcversion: v1ASM_TRAFFIC_TAG: v1template:metadata:labels:app: mockcversion: v1ASM_TRAFFIC_TAG: v1annotations:instrumentation.opentelemetry.io/inject-java: "true"instrumentation.opentelemetry.io/container-names: "default"spec:containers:- name: defaultimage: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-javaimagePullPolicy: IfNotPresentenv:- name: versionvalue: v1- name: appvalue: mockcports:- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:name: mocka-v2labels:app: mockaversion: v2
spec:replicas: 1selector:matchLabels:app: mockaversion: v2ASM_TRAFFIC_TAG: v2template:metadata:labels:app: mockaversion: v2ASM_TRAFFIC_TAG: v2annotations:instrumentation.opentelemetry.io/inject-java: "true"instrumentation.opentelemetry.io/container-names: "default"spec:containers:- name: defaultimage: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-javaimagePullPolicy: IfNotPresentenv:- name: versionvalue: v2- name: appvalue: mocka- name: upstream_urlvalue: "http://mockb:8000/"ports:- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:name: mockb-v2labels:app: mockbversion: v2
spec:replicas: 1selector:matchLabels:app: mockbversion: v2ASM_TRAFFIC_TAG: v2template:metadata:labels:app: mockbversion: v2ASM_TRAFFIC_TAG: v2annotations:instrumentation.opentelemetry.io/inject-java: "true"instrumentation.opentelemetry.io/container-names: "default"spec:containers:- name: defaultimage: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-javaimagePullPolicy: IfNotPresentenv:- name: versionvalue: v2- name: appvalue: mockb- name: upstream_urlvalue: "http://mockc:8000/"ports:- containerPort: 8000---
apiVersion: apps/v1
kind: Deployment
metadata:name: mockc-v2labels:app: mockcversion: v2
spec:replicas: 1selector:matchLabels:app: mockcversion: v2ASM_TRAFFIC_TAG: v2template:metadata:labels:app: mockcversion: v2ASM_TRAFFIC_TAG: v2annotations:instrumentation.opentelemetry.io/inject-java: "true"instrumentation.opentelemetry.io/container-names: "default"spec:containers:- name: defaultimage: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-javaimagePullPolicy: IfNotPresentenv:- name: versionvalue: v2- name: appvalue: mockcports:- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:name: mocka-v3labels:app: mockaversion: v3
spec:replicas: 1selector:matchLabels:app: mockaversion: v3ASM_TRAFFIC_TAG: v3template:metadata:labels:app: mockaversion: v3ASM_TRAFFIC_TAG: v3annotations:instrumentation.opentelemetry.io/inject-java: "true"instrumentation.opentelemetry.io/container-names: "default"spec:containers:- name: defaultimage: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-javaimagePullPolicy: IfNotPresentenv:- name: versionvalue: v3- name: appvalue: mocka- name: upstream_urlvalue: "http://mockb:8000/"ports:- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:name: mockb-v3labels:app: mockbversion: v3
spec:replicas: 1selector:matchLabels:app: mockbversion: v3ASM_TRAFFIC_TAG: v3template:metadata:labels:app: mockbversion: v3ASM_TRAFFIC_TAG: v3annotations:instrumentation.opentelemetry.io/inject-java: "true"instrumentation.opentelemetry.io/container-names: "default"spec:containers:- name: defaultimage: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-javaimagePullPolicy: IfNotPresentenv:- name: versionvalue: v3- name: appvalue: mockb- name: upstream_urlvalue: "http://mockc:8000/"ports:- containerPort: 8000---
apiVersion: apps/v1
kind: Deployment
metadata:name: mockc-v3labels:app: mockcversion: v3
spec:replicas: 1selector:matchLabels:app: mockcversion: v3ASM_TRAFFIC_TAG: v3template:metadata:labels:app: mockcversion: v3ASM_TRAFFIC_TAG: v3annotations:instrumentation.opentelemetry.io/inject-java: "true"instrumentation.opentelemetry.io/container-names: "default"spec:containers:- name: defaultimage: registry-cn-hangzhou.ack.aliyuncs.com/acs/asm-mock:v0.1-javaimagePullPolicy: IfNotPresentenv:- name: versionvalue: v3- name: appvalue: mockcports:- containerPort: 8000

对于每个实例服务 Pod,都加入了 instrumentation.opentelemetry.io/inject-java: "true"和instrumentation.opentelemetry.io/container-names: "default"两个注解,以声明该实例服务使用 java 语言实现,并要求 OpenTelemetry Operator 对名称为 default 的容器进行自动插装。

  1. 执行以下指令,部署实例服务。
kubectl apply -f mock.yaml

基于 OpenTelemetry 自动插装机制,部署的服务 Pod 将自动具有在调用链路中传递 baggage 的能力。

步骤三:创建泳道组和对应泳道

  1. 创建泳道组。

a. 登录 ASM 控制台 [ 7] ,在左侧导航栏,选择服务网格 > 网格管理

b. 在网格管理页面,单击目标实例名称,然后在左侧导航栏,选择流量管理中心 > 流量泳道

c. 在流量泳道页面,单击创建泳道组,在创建泳道组面板,配置相关信息,然后单击确定

image.png

  1. 创建 s1、s2、s3 泳道,并分别绑定 v1、v2、v3 版本。

a. 在流量泳道页面的流量规则定义区域,单击创建泳道

b. 在创建泳道对话框,配置相关信息,然后单击确定

image.png

创建 s1 泳道的示例图如下:

图片

三个泳道创建完成后,示例效果如下。默认情况下,您在泳道组中创建的第一个泳道将被设定为基线泳道。您也可以修改基线泳道,当流量发往其它泳道中不存在的服务时,通过回退机制将请求转发至基线泳道。关于修改基线泳道的具体操作,请参见修改基线泳道 [ 8]

图片

三个泳道创建完成后,针对泳道组中的每个服务都将生成泳道规则对应的目标规则 DestinationRule 和虚拟服务 VirtualService。您可以在控制台左侧导航栏,选择流量管理中心 > 目标规则虚拟服务进行查看。例如,针对 mocka 服务会自动创建如下 DestinationRule 和 VirtualService。

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:labels:asm-system: 'true'provider: asmswimlane-group: testname: trafficlabel-dr-test-default-mockanamespace: istio-system
spec:host: mocka.default.svc.cluster.localsubsets:- labels:ASM_TRAFFIC_TAG: v1name: s1- labels:ASM_TRAFFIC_TAG: v2name: s2apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:labels:asm-system: 'true'provider: asmswimlane-group: testname: trafficlabel-vs-test-default-mockanamespace: istio-system
spec:hosts:- mocka.default.svc.cluster.localhttp:- match:- headers:x-asm-prefer-tag:exact: s1route:- destination:host: mocka.default.svc.cluster.localsubset: s1fallback:target:host: mocka.default.svc.cluster.localsubset: s1- match:- headers:x-asm-prefer-tag:exact: s2route:- destination:host: mocka.default.svc.cluster.localsubset: s2fallback:target:host: mocka.default.svc.cluster.localsubset: s1- match:- headers:x-asm-prefer-tag:exact: s3route:- destination:host: mocka.default.svc.cluster.localsubset: s3fallback:target:host: mocka.default.svc.cluster.localsubset: s1
  1. 创建基于权重的统一引流规则。

a. 在流量泳道页面的流量规则定义区域,单击引流策略中的基于权重引流

b. 在设定统一引流规则对话框,配置相关信息,然后单击确定。本文以泳道服务对应入口 API 为 /mock 为例,为三条泳道配置统一的引流规则。

image.png

设定统一引流规则的示例图如下:

图片

  1. 设定三条泳道的引流权重,引流权重确定了流量向每条泳道发送的比例。

a. 在流量泳道页面的流量规则定义区域,在每条泳道的引流权重列,单击数字右侧的图片按钮,在编辑引流权重对话框,配置相关信息,然后单击确定

image.png

编辑流量权重的示例图如下:

图片

步骤四:验证全链路灰度功能是否生效

  1. 获取 ASM 网关的公网 IP。具体操作,请参见获取 ASM 网关地址 [ 9]

  2. 执行以下命令,设置环境变量。xxx.xxx.xxx.xxx 为上一步获取的 IP。

export ASM_GATEWAY_IP=xxx.xxx.xxx.xxx
  1. 验证全链路灰度功能是否生效。

a. 执行以下命令,查看三条泳道的访问效果。

for i in {1..100}; do curl http://${ASM_GATEWAY_IP}/mock ;  echo ''; sleep 1; done;

预期输出:

-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v3, ip: 192.168.0.2)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v2, ip: 192.168.0.184)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v2, ip: 192.168.0.189)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v2, ip: 192.168.0.184)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v2, ip: 192.168.0.189)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v3, ip: 192.168.0.2)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v2, ip: 192.168.0.184)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v2, ip: 192.168.0.189)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v2, ip: 192.168.0.184)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v2, ip: 192.168.0.189)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v3, ip: 192.168.0.2)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v2, ip: 192.168.0.184)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v2, ip: 192.168.0.189)
-> mocka(version: v2, ip: 192.168.0.184)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v2, ip: 192.168.0.189)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v3, ip: 192.168.0.2)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v3, ip: 192.168.0.2)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v2, ip: 192.168.0.184)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v2, ip: 192.168.0.189)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v3, ip: 192.168.0.2)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v3, ip: 192.168.0.2)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v2, ip: 192.168.0.184)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v2, ip: 192.168.0.189)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v3, ip: 192.168.0.2)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v2, ip: 192.168.0.184)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v2, ip: 192.168.0.189)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)
-> mocka(version: v1, ip: 192.168.0.193)-> mockb(version: v1, ip: 192.168.0.1)-> mockc(version: v1, ip: 192.168.0.190)

由预期输出得到,流量将以约 6:2:2 的比例发送到 s1、s2、s3 泳道,并由 s1 作为基线泳道,当调用链路中不存在某个服务的特定版本时,将会调用 s1 泳道中的对应服务。

总结

本文简要讨论了使用流量泳道来实现全链路流量灰度管理的场景与方案,并回顾了阿里云服务网格 ASM 提供的严格与宽松两种模式的流量泳道、以及这两种模式各自的优势与挑战。接下来介绍了一种基于 OpenTelemetry 社区提出的 baggage 透传能力实现的无侵入式的宽松模式泳道,这种类型的流量泳道同时具有对业务代码侵入性低、同时保持宽松模式的灵活特性的特点。同时,我们还介绍了新的基于权重的流量引流策略,这种策略可以基于统一的流量匹配规则,将匹配到的流量以设定好的比例分发到不同的流量泳道。

相关链接:

[1] baggage

https://opentelemetry.io/docs/concepts/signals/baggage/

[2] 创建 ASM 实例

https://help.aliyun.com/document_detail/147793.html#task-2370657

[3] 添加集群到 ASM 实例

https://help.aliyun.com/document_detail/148231.html#task-2372122

[4] 创建入口网关服务

https://help.aliyun.com/document_detail/150510.html#task-2372970

[5] 管理网关规则

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

[6] 开启 Sidecar 自动注入

https://help.aliyun.com/document_detail/186136.html#task-1962690

[7] ASM 控制台

https://servicemesh.console.aliyun.com/

[8] 修改基线泳道

https://help.aliyun.com/zh/asm/user-guide/scenario-1-the-drainage-request-header-is-not-transmitted-in#0561972057jqm

[9] 获取 ASM 网关地址

https://help.aliyun.com/document_detail/444079.html#section-ida-zt6-md7

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/25495.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据数仓的数据回溯

在大数据领域,数据回溯是一项至关重要的任务,它涉及到对历史数据的重新处理以确保数据的准确性和一致性。 数据回溯的定义与重要性 数据回溯,也称为数据补全,是指在数据模型迭代或新模型上线后,对历史数据进行重新处理…

开源多平台AI音乐生成器本地安装结合cpolar内网穿透实现远程访问

文章目录 前言1. 本地部署2. 使用方法介绍3. 内网穿透工具下载安装4. 配置公网地址5. 配置固定公网地址 前言 本文主要介绍如何在Windows系统电脑上快速本地部署一个文字生成音乐的AI创作工具MusicGPT,并结合cpolar内网穿透工具实现随时随地远程访问使用。 MusicG…

基于stm32最小版的超声波测距模块

目录 一、模块准备 二、HC-SR04模块原理解释 三、程序完整代码 四、烧录结果 总结 一、模块准备 STM32F103C8T6 HC-SR04 ST-Link(其他烧录器也可以) 0.96寸OLED屏幕(非必须,仅供显示测距结果,可以使用串口助手代替…

nodejs最新某东h5st(4.7.2)参数分析与javascript逆向纯算法还原(含算法源码)(2024-06-09)

一、作者声明: 文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除! 二 、写在前面 h5st从4.1一路更新到4.7.2,逐渐vmp…

66. UE5 RPG 实现远程攻击武器配合角色攻击动画

在制作游戏中,我们制作远程攻击角色,他们一般会使用弓箭,弩,弹弓等武器来进行攻击。比如你使用弓箭时,如果角色在播放拉弓弦的动画,但是弓箭武器没有对应的表现,会显得很突兀。所以,…

k8s和deepflow部署与测试

Ubuntu-22-LTS部署k8s和deepflow 环境详情: Static hostname: k8smaster.example.net Icon name: computer-vm Chassis: vm Machine ID: 22349ac6f9ba406293d0541bcba7c05d Boot ID: 605a74a509724a88940bbbb69cde77f2 Virtualization: vmware Operating System: U…

克鲁斯卡尔算法最小生成树--C语言

同样是最小生成树,普利姆算法是从一个起始顶点开始,逐步扩展生成树,每次选择连接生成树和未包含顶点的最小边。而克鲁斯卡尔算法是按权值排序的方式,从最小的边开始逐步添加到生成树中,确保不会形成环,直到…

自友科技破解走班教育排课难题

新高考后,校园教务都面临着晋级,其中走班教育的分班排课是个巨大的挑战。 所以在分班排课的时候要清楚一下几个问题 一是:清楚的核算学生的选考科目。学生选科提交后做好并承认,最好是在分班后不要改或很少的一部分人改动。 二是…

达梦8 探寻达梦排序原理:传统排序机制(SORT_FLAG=0)

测试版本:--03134283938-20221019-172201-20018 达梦的排序机制由四个dm.ini参数控制: #maximum sort buffer size in Megabytes ,有效值范围(1~2048) SORT_BUF_SIZE 100 #ma…

SpringBoot: 启动流程和类装载

前面我们学过Spring定制了自己的可执行jar,将真正执行时需要的类和依赖放到BOOT-INF/classes、BOOT-INF/lib来,为了能够识别这些为止的源文件,Spring定制了自己类加载器,本节我们来讲解这个类加载器。本节涉及的内容主要包括: Sp…

Linux部署调度工具xxl-job

背景: Pentaho Data Integration(kettle)作为用户规模最多的开源ETL工具,强大简洁的功能深受广大ETL从业者的欢迎。但kettle本身的调度监控功能却非常弱。Pentaho官方都建议采用crontab(Unix,linux平台)和计划任务(Win…

群体优化算法----树蛙优化算法介绍以及应用于资源分配示例

介绍 树蛙优化算法(Tree Frog Optimization Algorithm, TFO)是一种基于群体智能的优化算法,模拟了树蛙在自然环境中的跳跃和觅食行为。该算法通过模拟树蛙在树枝间的跳跃来寻找最优解,属于近年来发展起来的自然启发式算法的一种 …

抽象的java入门1.3.2

前言: 全新版本的函数(方法)定义,更简单 1.优化了验证过程,直击本质 2.新增目前一图流 正片: 函数的结构可以分为三部分:函数名,参数,函数体 一生二,二生…

6.9总结

Vue生命周期 生命周期:指一个对象从创建到销毁的整个过程生命周期的八个阶段:每触发一个生命周期事件,会自动执行一个生命周期的方法(钩子) mounted:挂载完成,Vue初始化成功,HTML渲…

ssm629基于SSM的二手交易平台设计与开发+jsp【已测试】

前言:👩‍💻 计算机行业的同仁们,大家好!作为专注于Java领域多年的开发者,我非常理解实践案例的重要性。以下是一些我认为有助于提升你们技能的资源: 👩‍💻 SpringBoot…

智慧社区整体解决方案

1.智慧社区整体建设方案内容 2.整体功能介绍

linux动态调试 dev_dbg

动态调试使用方法 打开内核动态调试开关,make menuconfig选中CONFIG_DYNAMIC_DEBUG以及CONFIG_DEBUG_FS Linux启动后,使用命令行挂载上dbgfs 1. mkdir /mnt/dbg 2. mount -t debugfs none /mnt/dbg 1.控制某个文件所有dev_dbg(), echo -n &q…

sqli-labs 靶场 less-11~14 第十一关、第十二关、第十三关、第十四关详解:联合注入、错误注入

SQLi-Labs是一个用于学习和练习SQL注入漏洞的开源应用程序。通过它,我们可以学习如何识别和利用不同类型的SQL注入漏洞,并了解如何修复和防范这些漏洞。Less 11 SQLI DUMB SERIES-11判断注入点 尝试在用户名这个字段实施注入,且试出SQL语句闭合方式为单…

电子阅览室有何作用

随着互联网的快速发展,电子阅览室逐渐成为人们获取知识的新方式。它为读者提供了便捷、高效的阅读体验,具有诸多作用。首先,电子阅览室拥有丰富的电子书籍资源,涵盖了各个领域的知识。无论是文学作品还是学术论文,读者…

解决Win10系统ping不通、无法远程的问题

1、概述 某天要使用微软的远程桌面程序mstsc.exe远程到旁边的一台测试电脑上,结果远程不了,ping都ping不通,于是详细研究了这个问题。在此大概地记录一下该问题排查的过程,以供参考。 2、ping不通 使用mstsc.exe远程到测试电脑,远程不了,没有反应。于是手动ping一…