当前位置:   article > 正文

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

适应多样化需求: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" 的标识。这样,我们就可以对灰度流量进行标记和识别。

2. 定义插件扩展配置。

  1. type ParamsRandomConfig struct {
  2. # 参数比例功能开关
  3. paramsRandomEnable bool
  4. # 参数比例依据哪个Header的值,例如userId
  5. paramsRandomHeaderKey string
  6. # 参数比例的百分比值,
  7. paramsPercentageRatio int64
  8. }

3. 解析插件扩展参数,在控制台插件配置中填写的 YAML 配置会自动转换为 JSON,此处直接从 JSON 这个参数里解析配置即可。

  1. // 在控制台插件配置中填写的YAML配置会自动转换为JSON,此处直接从JSON这个参数里解析配置即可
  2. func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
  3. // 解析出配置,更新到config中
  4. config.paramsRandomEnable = json.Get("paramsRandomEnable").Bool()
  5. config.paramsRandomHeaderKey = json.Get("paramsRandomHeaderKey").String()
  6. config.paramsPercentageRatio = json.Get("paramsPercentageRatio").Int()
  7. return nil
  8. }

4. 请求处理 Filter 编写。

  1. func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
  2. if config.paramsRandomEnable {
  3. randomHeaderValue, err := proxywasm.GetHttpRequestHeader(config.paramsRandomHeaderKey)
  4. if err != nil {
  5. proxywasm.LogErrorf("get header enhance error: %v", err)
  6. return types.ActionContinue
  7. }
  8. // 取目标参数值的 hash ,用于百分比值计算
  9. hash := sha256.Sum256([]byte(randomHeaderValue))
  10. hashInt := new(big.Int)
  11. hashInt.SetBytes(hash[:])
  12. modulo := new(big.Int).Mod(hashInt, big.NewInt(100))
  13. result := modulo.Cmp(big.NewInt(config.paramsPercentageRatio))
  14. if result <= 0 {
  15. // 写入 x-mse-tag=gray 说明该请求流量标为 gray,在后续链路中会优先去玩gray环境的节点,
  16. // 如果对应的应用没有gray环境,会fallback到基线环境
  17. proxywasm.AddHttpRequestHeader("x-mse-tag", "gray")
  18. } else {
  19. // 不符合灰度条件的流量
  20. proxywasm.LogInfof("set header false value: %s, hash: %s", randomHeaderValue, hashInt)
  21. }
  22. }
  23. return types.ActionContinue
  24. }

5. 编译生成 WASM 文件

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

  1. go mod tidy
  2. tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags='custommalloc nottinygc_finalizer' ./main.go

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

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

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

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

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

7. 观察插件日志

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

总结

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

  • 根据用户标识进行灰度

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

  • 根据地理位置进行灰度

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

  • 基于流量比例的灰度

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

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

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

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

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

参考链接:

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

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)

https://help.aliyun.com/zh/mse/user-guide/14/?spm=a2c4g.11186623.0.0.73062e8dd0miqK

作者:十眠

原文链接

本文为阿里云原创内容,未经允许不得转载。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/480608
推荐阅读
相关标签
  

闽ICP备14008679号