适应多样化需求:WASM 插件在全链路灰度发布中的应用

作者:十眠

据调研数据显示,约 70% 的生产故障是由变更引起的。为了消除变更过程存在的风险,在发布过程中,我们总是希望能够用小部分特定流量来验证下新发布应用是否正常。即使新版本有问题,也能及时发现,控制影响面,保障了整体的稳定性,这就是微服务架构下的全链路灰度的能力。

MSE 在微服务全链路灰度场景下提供了一套成熟完善且开箱即用的能力。

随着企业微服务化改造的深入,对微服务治理的场景与应用也有了更多的诉求,全链路灰度就是如此。MSE 默认支持按照内容规则与百分比规则的灰度路由策略,其中按照内容灰度支持 header、params 等参数件支持精确/前缀/正则等多种匹配策略,满足常见全链路灰度场景的诉求。如果我们遇到较为复杂的场景,发现 MSE 提供的策略无法满足我们诉求时,应该怎么解决?

接下来,我们来一起讨论几个合理且较为复杂的灰度需求。

很多复杂且合理的灰度诉求

其实关于全链路灰度有其他很多合理的诉求,比如:

  1. 我们希望随机百分比可以根据参数特征来调整,这样对于每个用户来说,是否被灰度是固定的,多次调用体验一致。

  2. 我们来自于手机客户端的流量带有 version 特征、来自网页流量又是带有 tag 的特征,我们期望两者满足任一条件的流量去往灰度环境即流量条件匹配为"或"的模式;

  3. 来自我们生产流量确实比较大,我们期望第一批灰度的流量可以控制到整体 1‰ 流量的灰度诉求;

  4. 我们期望可以基于流量 Body 参数解析的灰度诉求。

面对一系列复杂并带有定制需求的合理诉求,产品层面很难做到完全支持。这些诉求在企业客户的生产实际中非常常见,而当前的 MSE 控制台配置方案似乎并不能完美应对这些多样化的实际场景。毕竟,当我们将目光转向不同企业客户的生产实践时,会发现复杂场景的变化和多样性只会更加显著。那么,我们如何能够有效地满足复杂环境下全链路灰度发布的诉求呢?

云原生网关 WASM 插件

什么是 WASM?WASM(WebAssembly)是一种可移植、高性能的二进制指令集,用于在 Web 浏览器中运行代码。Envoy 使用 WASM 作为插件扩展机制,允许开发人员编写自定义的功能扩展,以满足特定的需求。

云原生网关 WASM 插件扩展机制的工作原理如下:

  1. MSE 云原生网关提供了插件市场,供我们编写自定义的 WASM 插件来满足各种扩展的诉求,如请求/响应转换、过滤器、身份验证等。同时编写 WASM 插件支持(Go、Rust、类 JS、lua 等)。

  2. 我们只需要将编译好的 WASM 文件通过自定义插件的方式上传到插件市场,MSE 云原生网关会将其加载到 Envoy 中。

  3. 当云原生网关处理网络流量时,它会根据配置将流量传递给适当的 WASM 插件进行处理,即上图的 Custom Filters。WASM 插件可以读取和修改请求/响应数据,执行自定义逻辑,并将流量传递给下一个插件或最终目标。

MSE 插件市场还提供了一些默认认证鉴权、流量管控、安全防护等平台官方插件,可以帮助我们提升网关的安全与稳定性,并且支持多语言自定义扩展,满足网关上自定义流量治理需求。

MSE WASM 插件扩展机制的优点包括:

  1. 借助 WASM 特性支持多语言扩展,提供了灵活性和可扩展性,可以通过 WASM 插件编写开发,满足特定的业务需求。

  2. 网关 Wasm 插件与开源 Envoy100% 兼容,不存在锁定。

  3. 提供插件市场,网关的二次扩展功能均通过插件提供给用户按需使用。

  4. 插件采用热更新机制,在沙盒中执行,对网关自身稳定性无影响。

WASM 插件以其独特的轻量级和高效性能特点,为云原生网关带来了创新的扩展能力,而这一切不会带来明显的性能开销。WASM 插件运行在沙箱环境中,提供了一种安全可控的方式来部署自定义逻辑,这样不仅保障了网关的灵活性和可扩展性,也确保了对整体性能的最小影响。

看起来 MSE 云原生网关的 WASM 插件确实是一种优雅且便捷的方式,能够满足各种全链路灰度的需求。接下来,我将通过编写 WASM 插件来实现在复杂条件下的全链路灰度。

通过 WASM 插件实现参数比例

上文提到,WASM 插件可以支持多语言扩展,我们可以选择我们擅长的语言进行开发,本文以 Go 语言为例。

云原生网关提供了 wrapper 包以及相关的 API 供我们快速编写 WASM 插件。

  1. 云原生网关配置基于 x-mse-tag 的灰度路由,详见基于 MSE 云原生网关实现全链路灰度 [ 1]

服务治理泳道配置如下:

云原生网关路由配置如下:

我们创建灰度泳道,只要 header 中存在 x-mse-tag=gray 的请求都会被认为是灰度流量,且在后续链路中都会优先去往灰度环境。因此在 WASM 插件中,我们可以对流量进行任意自定义的计算和匹配。只要符合我们的灰度条件,我们就可以在请求头中添加一个名为 "x-mse-tag" 值为 "gray" 的标识。这样,我们就可以对灰度流量进行标记和识别。

  1. 定义插件扩展配置。
csharp 复制代码
type ParamsRandomConfig struct {
    # 参数比例功能开关
    paramsRandomEnable    bool
    # 参数比例依据哪个Header的值,例如userId
  paramsRandomHeaderKey string
    # 参数比例的百分比值,
    paramsPercentageRatio     int64
}
  1. 解析插件扩展参数,在控制台插件配置中填写的 YAML 配置会自动转换为 JSON,此处直接从 JSON 这个参数里解析配置即可。
lua 复制代码
// 在控制台插件配置中填写的YAML配置会自动转换为JSON,此处直接从JSON这个参数里解析配置即可
func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
  // 解析出配置,更新到config中
  config.paramsRandomEnable = json.Get("paramsRandomEnable").Bool()
  config.paramsRandomHeaderKey = json.Get("paramsRandomHeaderKey").String()
  config.paramsPercentageRatio = json.Get("paramsPercentageRatio").Int()

  return nil
}
  1. 请求处理 Filter 编写。
go 复制代码
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
  if config.paramsRandomEnable {
    randomHeaderValue, err := proxywasm.GetHttpRequestHeader(config.paramsRandomHeaderKey)
    if err != nil {
      proxywasm.LogErrorf("get header enhance error: %v", err)
      return types.ActionContinue
    }

    // 取目标参数值的 hash ,用于百分比值计算
    hash := sha256.Sum256([]byte(randomHeaderValue))
    hashInt := new(big.Int)
    hashInt.SetBytes(hash[:])

    modulo := new(big.Int).Mod(hashInt, big.NewInt(100))
    result := modulo.Cmp(big.NewInt(config.paramsPercentageRatio))
    if result <= 0 {
      // 写入 x-mse-tag=gray 说明该请求流量标为 gray,在后续链路中会优先去玩gray环境的节点,
      // 如果对应的应用没有gray环境,会fallback到基线环境
      proxywasm.AddHttpRequestHeader("x-mse-tag", "gray")
    } else {
      // 不符合灰度条件的流量
      proxywasm.LogInfof("set header false value: %s, hash: %s", randomHeaderValue, hashInt)
    }
  }
  return types.ActionContinue
}
  1. 编译生成 WASM 文件

我们通过如下命令编译生成 WASM 文件。

css 复制代码
go mod tidy
tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags='custommalloc nottinygc_finalizer' ./main.go

编译成功会在当前目录下创建文件 main.wasm。该文件在下文本地调试的示例中也会被用到。

在使用云原生网关插件市场的自定义插件功能时,直接上传该文件即可。

  1. 配置参数并验证参数比例功能

如上图所示,我们指定 Header 中的 userId 为百分比依据的参数,并且配置了 10% 流量灰度的比例值。点击保存后配置,实时生效。

请求过程中 userId=1 的 header 恒定去往灰度环境,userId=11 的请求恒定去往基线环境。

  1. 观察插件日志

到目前为止,我们通过编写 WASM 插件实现了根据特定 Header 的参数比例需求。

总结

通过 WASM 插件,我们可以实现各种全链路灰度的需求,包括但不限于以下几个方面:

  • 根据用户标识进行灰度

    可以根据用户的身份、角色、权限等信息将特定用户的请求路由到相应的灰度环境,以实现个别用户的全链路灰度。

  • 根据地理位置进行灰度

    可以根据用户的地理位置信息将请求路由到特定地区的灰度环境,以满足特定地区的全链路灰度需求。

  • 基于流量比例的灰度

    可以根据流量比例将请求路由到不同的灰度环境,以实现按比例分配流量的全链路灰度。

  • 基于请求包复杂属性的灰度

    可以根据请求的属性,如请求头、请求体、查询参数等信息,来判断是否满足特定条件,从而路由请求到相应的灰度环境。

利用 WASM 插件的强大适应性,我们可以针对性地编写插件以适应不同的全链路灰度发布需求。这为定制化业务场景提供了无限的可能性,使得灰度测试和发布可以根据独特的业务要求灵活执行。特别是对于计算密集型和无状态的任务,如认证鉴权、请求/响应的加密和混淆、内容转换等,将这些逻辑部署在网关层是理想选择。它不仅保持了系统的简洁和灵活性,而且确保了核心网关功能的低性能损失,这在优化资源使用和维护服务品质方面都提供了显著的好处。

目前 MSE WASM 插件支持 Redis 访问,当然 WASM 插件也不是万能的,如果逻辑里需要对接数据库,或者要起多线程处理,就不适合做成网关插件,当前 WASM 插件也不支持这些能力。

参考链接:

1\] 基于 MSE 云原生网关实现全链路灰度*[help.aliyun.com/zh/mse/user...](https://link.juejin.cn?target=https%3A%2F%2Fhelp.aliyun.com%2Fzh%2Fmse%2Fuser-guide%2Fimplement-an-end-to-end-canary-release-by-using-mse-cloud-native-gateways%3Fspm%3Da2c4g.11186623.0.0.226a5446EBhK5X "https://help.aliyun.com/zh/mse/user-guide/implement-an-end-to-end-canary-release-by-using-mse-cloud-native-gateways?spm=a2c4g.11186623.0.0.226a5446EBhK5X")* \[2\] 开发插件_微服务引擎(MSE) *[help.aliyun.com/zh/mse/user...](https://link.juejin.cn?target=https%3A%2F%2Fhelp.aliyun.com%2Fzh%2Fmse%2Fuser-guide%2F14%2F%3Fspm%3Da2c4g.11186623.0.0.73062e8dd0miqK "https://help.aliyun.com/zh/mse/user-guide/14/?spm=a2c4g.11186623.0.0.73062e8dd0miqK")*

相关推荐
阿里云云原生3 小时前
【昨晚 17:00】模力工场联合 HiClaw,聊聊怎么把虾场管明白
云原生
阿里云云原生6 小时前
连登顶会!阿里云多项研究成果大幅提升运维智能精度与效率
云原生
阿里云云原生7 小时前
从养一只虾到开好虾场,HiClaw 规模化养虾的详细解读
云原生
河码匠8 小时前
Kubernests YAML 详细之卷(PV、PVC、StorageClass)
云原生·容器·kubernetes
码上上班9 小时前
k8s控制器,daemonset
云原生·容器·kubernetes
深念Y10 小时前
Docker Desktop 版本与 IDEA 插件兼容性
docker·云原生·容器·api·idea·wsl
llm大模型算法工程师weng11 小时前
AI + Docker + K8s:云原生时代的运维提效实战
运维·人工智能·云原生
步步为营DotNet12 小时前
全面解读C# 14在云原生微服务开发中的创新应用
微服务·云原生·c#
平行云PVT21 小时前
数字孪生信创云渲染技术解析:从混合信创到全国产化架构
linux·unity·云原生·ue5·图形渲染·webgl·gpu算力
heimeiyingwang1 天前
【架构实战】云原生架构设计原则
云原生·架构