Higress 实战: 30行代码写一个 Wasm Go 插件

news2025/7/27 12:31:35

前言

在11月15号的直播 《Higress 开源背后的发展历程和上手 Demo 演示》中,为大家演示了 Higress 的 Wasm 插件如何面向 Ingress 资源进行配置生效,本文对当天的 Demo 进行一个回顾,并说明背后的原理机制。

本文中 Demo 运行的前提,需要在 K8s 集群中安装了 Higress,并生效了下面这份 quickstart 配置:

https://github.com/alibaba/higress/releases/download/v0.5.2/quickstart.yaml

这个 Demo 要实现的功能是一个 Mock 应答的功能,需要实现根据配置的内容,返回 HTTP 应答。

本文会按以下方式进行介绍:

  • 编写代码:代码逻辑解析
  • 生效插件:说明代码如何进行编译打包并部署生效
  • 测试插件功能:说明全局粒度,路由/域名级粒度如何生效
  • 插件生效原理:对整体流程进行回顾,说明插件生效的原理
  • 三个革命性的特性:介绍 Wasm 插件机制为网关插件开发带来的变革

编写代码

package main

import (
    . "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
    "github.com/tidwall/gjson"
)

func main() {
    SetCtx(
        "my-plugin",
        ParseConfigBy(parseConfig),
        ProcessRequestHeadersBy(onHttpRequestHeaders),
    )
}

type MyConfig struct {
    content string
}

func parseConfig(json gjson.Result, config *MyConfig, log Log) error {
    config.content = json.Get("content").String()
    return nil
}

func onHttpRequestHeaders(ctx HttpContext, config MyConfig, log Log) types.Action {
    proxywasm.SendHttpResponse(200, nil, []byte(config.content), -1)
    return types.ActionContinue
}

上面代码中可以看到三个函数:

  • main:插件通过 main 函数定义插件上下文,包括插件名称,用于解析配置的函数,以及用于处理请求/应答的函数
  • parseConfig:这个函数通过在 SetCtx 中指定的 ParseConfigBy 被挂载到插件配置解析阶段,传入的三个参数分别是:
    • json:传入插件的配置,将统一序列化为一个 json 字典对象,提供 parseConfig 进行解析
    • config:parseConfig 将解析后的插件配置输出到这个 MyConfig 对象
    • log:提供日志输出接口
  • onHttpRequestHeaders:函数中调用的 proxywasm.SendHttpResponse,用于实现直接返回 HTTP 应答,这个函数通过在 SetCtx 中指定的 ProcessRequestHeadersBy 被挂载到解析请求 Header 的执行阶段,其他的挂载方式还有:
    • ProcessRequestBodyBy:挂载到解析请求 Body 的执行阶段
    • ProcessResponseHeadersBy:挂载到构造应答 Header 的执行阶段
    • ProcessResponseBodyBy:挂载到构造应答 Body 的执行阶段

传入的三个参数分别是:

    • ctx:用于获取请求上下文,如 scheme/method/path 等,通过 ctx 可以设置自定义上下文,能跨执行阶段访问
    • config:提供 parseConfig 解析好的自定义配置
    • log:提供日志输出接口

这个 30 行代码实现的插件功能比较简单,这里有一些功能相对复杂的例子:https://github.com/alibaba/higress/tree/main/plugins/wasm-go/extensions

这里有插件 sdk 的详细使用文档:

https://higress.io/zh-cn/docs/user/wasm-go.html

这个插件 sdk 是基于 Tetrate 社区的 proxy-wasm-go-sdk 实现的,如果关注更底层的细节,可以查看:

https://github.com/tetratelabs/proxy-wasm-go-sdk

https://github.com/alibaba/higress/blob/main/plugins/wasm-go/pkg/wrapper

可以看到,Higress 的 wasm-go sdk 是通过 Go 1.18 引入的泛型特性封装了插件上下文处理细节,从而降低插件开发所需代码量,开发者只用关心配置解析和请求应答处理的逻辑。

生效插件

编写完成代码后,一共有三个步骤,实现插件逻辑的生效:

  1. 编译:将 go 代码编译成 Wasm 格式文件
  2. 镜像推送:将 Wasm 文件打包成 docker 镜像,并推送至镜像仓库
  3. 下发配置:在 K8s 上创建 WasmPlugin 资源

编译

将上面的 Go 文件 main.go 编译成 plugin.wasm

tinygo build -o plugin.wasm -scheduler=none -target=wasi main.go

镜像推送

编写 Dockerfile

FROM scratch
COPY plugin.wasm ./

构建并推送 Docker 镜像 (这里示例用的是 Higress 的官方镜像仓库)

docker build -t higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/demo:1.0.0 .
docker push higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/demo:1.0.0

下发配置

编写 wasmplugin.yaml,配置说明:

  • selector: 选中了默认安装在 higress-system 命名空间下的 higress-gateway 生效这份插件
  • pluginConfig:插件配置,最终会被转换成上面代码中的 MyConfig 对象
  • url:填写镜像地址,需要以"oci://"开头

除了这些配置外,还可以定义插件的执行阶段和优先级等进阶配置,可以参考 Istio API 官方文档:https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/

# wasmplugin.yaml
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: mock-response
  namespace: higress-system
spec:
  selector:
    matchLabels:
      higress: higress-system-higress-gateway
  pluginConfig:
    content: "hello higress"
  url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/demo:1.0.0

通过 kubectl 创建这个资源

kubectl apply -f wasmplugin.yaml

测试插件功能

基于之前生效的 quickstart.yaml,目前集群中的 Ingress 访问拓扑如下所示:

未生效插件的情况下:

  • 请求/foo 将返回 HTTP 应答 "foo"
  • 请求/bar 将返回 HTTP 应答 "bar"

全局生效

基于上文生效插件阶段,下发的 wasmplugin.yaml,生效插件后效果如下:

  • 请求/foo 将返回 HTTP 应答 "hello higress"
  • 请求/bar 将返回 HTTP 应答 "hello higress"

域名&路由级生效

将 wasmplugin.yaml 配置修改如下

# wasmplugin.yaml
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
  name: mock-response
  namespace: higress-system
spec:
  selector:
    matchLabels:
      higress: higress-system-higress-gateway
  pluginConfig:
    content: "hello higress"
    _rules_:
    - content: "hello foo"
      _match_route_:
      - "default/foo"
    - content: "hello bar"
      _match_route_:
      - "default/bar"
    - content: "hello world"
      _match_domain_:
      - "*.example.com"
      - "www.test.com"
  url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/demo:1.0.0

在 pluginConfig 中增加了 _rules_ 规则列表,规则中可以指定匹配方式,并填写对应生效的配置:

  • _match_route_:匹配 Ingress 生效,匹配格式为:Ingress 所在命名空间 + "/" + Ingress 名称
  • _match_domain_:匹配域名生效,填写域名即可,支持通配符

生效这份修改后的配置:

kubectl apply -f wasmplugin.yaml

可以看到效果如下:

  • 请求/foo 将返回 HTTP 应答 "hello foo" (匹配到第一条 rule)
  • 请求/bar 将返回 HTTP 应答 "hello bar" (匹配到第二条 rule)
  • 请求www.example.com 将返回 HTTP 应答 "hello world" (匹配到第三条 rule)
  • 请求www.abc.com 将返回 HTTP 应答 "hello higress" (没有匹配的 rule,使用全局配置)

插件生效原理

这里对插件的生效机制简单做个说明:

  1. 用户将代码编译成 wasm 文件
  2. 用户将 wasm 文件构建成 docker 镜像
  3. 用户将 docker 镜像推送至镜像仓库
  4. 用户创建 WasmPlugin 资源
  5. Istio watch 到 WasmPlugin 资源的变化
  6. Higress Gateway 中的 xDS proxy 进程从 Istio 获取到配置,发现插件的镜像地址
  7. xDS proxy 从镜像仓库拉取镜像
  8. xDS proxy 从镜像中提取出 wasm 文件
  9. Higress Gateway 中的 envoy 进程从 xDS proxy 获取到配置,发现 wasm 文件的本地路径
  10. envoy 从本地文件中加载 wasm 文件

这里 envoy 获取配置并加载 wasm 文件使用到了 ECDS (Extension Config Discovery Service)的机制,实现了 wasm 文件更新,直接热加载,不会导致任何连接中断,业务流量完全无损。

三个革命性的特性

上面的 Wasm 插件机制为网关自定义插件开发带来了三个革命性的特性。

特性一:插件生命周期和网关解耦

这个特性主要得益于 Istio 的 WasmPlugin 机制设计。可以和 K8s Nginx Ingress 的插件机制做个对比:

reference:  https://github.com/kubernetes/ingress-nginx/blob/main/rootfs/etc/nginx/lua/plugins/README.md
Installing a plugin

There are two options:
mount your plugin into /etc/nginx/lua/plugins/<your plugin name> in the ingress-nginx pod
build your own ingress-nginx image like it is done in the  example and install your plugin during image build

可以看到 Nginx Ingress 加载自定义插件,需要将 lua 文件挂载进 pod,或者在构建镜像时装入。这样就将插件的生命周期跟网关绑定在一起,插件逻辑更新,需要发布新版本,网关也需要发布新版本或者重新部署。

使用 WasmPlugin 的机制,插件需要发布新版本,只需构建插件自身的镜像并进行下发生效,而且可以基于镜像的 tag 进行插件的版本管理。这样插件变更,不仅无需重新部署网关,结合 Envoy 的 ECDS 机制对流量也是完全无损。

特性二:高性能的多语言支持

基于 Wasm 的能力,可以用多种语言编写插件,对开发人员更加友好。实现多语言开发插件的另一种方式是基于 RPC 和网关进程通信的外置进程/服务插件,这种模式会有额外的 IO 开销,并且附加的进程/服务也带来额外的运维复杂度。目前大家对 Wasm 插件的性能比较关心,从我们的测试数据来看,指令执行性能相比原生的 C++ 语言确实有差距,但性能和 Lua 持平,且远好于外置插件。

对于一段逻辑:循环执行20次请求头设置,循环执行20次请求头获取,循环执行20次请求头移除。我们对比了分别用 Lua 和不同语言实现的 Wasm 的处理性能,下面是对单个请求延时的影响对比:

特性三:安全沙箱

Envoy 目前支持多种 Wasm 的运行时,例如 V8,WAMR,wasmtime 等等,这些运行时均提供了安全沙箱能力,即 Wasm 插件中出现了访问空指针、异常未捕获等逻辑,也不会令 Envoy 宿主进程 Crash。并且可以通过配置,在插件逻辑出现异常后进行 Fail Open 处理,跳过插件的执行逻辑,将对业务的影响降至最低。

原文链接

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

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

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

相关文章

PPOCR车牌定位模型推理后处理优化研究

综述 最近在研究基于PPOCR算法的车牌识别&#xff08;LPR&#xff09;&#xff0c;部署模型后发现之前关于OCR文本定位的后处理策略在车牌识别中存在定位精度不够高&#xff0c;文本框偏移的问题&#xff0c;如&#xff1a; 经分析发现是之前的OCR后处理策略存在一定局限&am…

java刷题day 03

选择题&#xff1a; 解析&#xff1a; 父类private的成员变量&#xff0c;根据权限修饰符的访问控制范围&#xff0c;只有在类内部才能被访问&#xff0c;就算是他的子类&#xff0c;也不能访问。这里如果将Person p new Child();改成 Person p new Person();代码依然无法通过…

乐趣国学—品读《弟子规》中的“余力学文”之道

文章目录余力学文不力行 但学文 长浮华 成何人但力行 不学文 任己见 昧理真读书法 有三到 心眼口 信皆要方读此 勿慕彼 此未终 彼勿起宽为限 紧用功 工夫到 滞塞通心有疑 随札记 就人问 求确义房室清 墙壁净 几案洁 笔砚正墨磨偏 心不端 字不敬 心先病列典籍 有定处 读看毕 还原…

信号完整性测试,关于SMA装配的细节,很多人都忽视了

作者 | 萧隐君&#xff0c;仿真秀专栏作者 SMA转接头是射频微波、天线和高速电路测试经常用到的一种连接器&#xff0c;应用非常广泛&#xff0c;种类也很多。在信号完整性的测试夹具中&#xff0c;2.92mm的SMA用的较多&#xff0c;它的带宽可以到40GHz&#xff0c;对于25Gbps…

【全网独家,收藏吧】10年全部《信息资源管理》真题整理,第2章 信息化规划与组织

文章目录&#x1f525; 11 年 4 月《信息资源管理》真卷选择题名词解释综合分析题&#x1f525; 11 年 7 月《信息资源管理》真卷选择题名词解释题简答题⭐ 12 年 4 月《信息资源管理》真卷选择题简答题⭐ 12 年 7 月《信息资源管理》真卷选择题简答题⭐ 13 年 4 月《信息资源管…

计算机网络--- 电子邮件

&#xff08;一&#xff09;电子邮件系统的组成 电子邮件是一种异步通信方式&#xff0c;通信时不需要双方同时在场。电子邮件把邮件发送到收件人使用的邮件服务器&#xff0c;并放在其中的收件人邮箱中&#xff0c;收件人可以随时上网到自己使用的邮件服务器进行读取。 一…

补盲激光雷达大爆发,各路产品谁领风骚?

11月伊始车载激光雷达赛道上演了冰火两重天的景象。国外Ouster与Velodyne LiDAR宣布合并以抱团取暖&#xff0c;主打OPA技术的Quanergy甚至股市停牌&#xff0c;一时风声鹤唳&#xff0c;寒意阵阵&#xff1b;而反观国内&#xff0c;禾赛、速腾、亮道相继发布纯固态补盲激光雷达…

龙格-库塔法(Runge-Kutta methods)

非线性的常微分方程通常是难以求出解析解的&#xff0c;只能通过多次迭代求近似的数值解。 龙格&#xff0d;库塔法&#xff08;Runge-Kutta methods&#xff09;是用于非线性常微分方程的解的重要的一类隐式或显式迭代法。简写做RK法。 对于任意的Yf(X),假设某点(Xi,Yi)的斜…

固定资产管理系统能帮助企业解决哪些问题?

固定资产管理系统是企业信息化转型中重要的工具之一。固定资产在企业整体资金和运营管理中的占比非同一般&#xff0c;因此企业管理者对固定资产的重视程度也逐渐提升。随着企业固定资产数量和种类的增多、人员的增多&#xff0c;以及分支机构和部门的增多&#xff0c;单纯依靠…

数据安全治理白皮书4.0(附下载link)

数据安全治理白皮书是国内最早的数据安全治理白皮书系列&#xff0c;围绕数据安全治理&#xff0c;“新理论、新技术、新实践”&#xff0c;一次系统汇总、梳理分析与集中呈现&#xff0c;2018年-2021年&#xff0c;已发布1.0/2.0/3.0三个版本&#xff0c;2022年&#xff0c;已…

LeetCode | 循环队列的爱情【恋爱法则——环游世界】

兜兜转转⚪还是你❤✒前言环形队列的概念拓展&#xff1a;生产者与消费者一、题目描述二、思路分析&#x1f351;初次遇见她♀【是心动的感觉】&#x1f351;阻碍一&#xff1a;队空还是队满不好区分【性格互异】&#x1f351;解决方案&#x1f351;阻碍二&#xff1a;很难获取…

Git之借助Commitizen规范化提交代码

文章目录一、约定式提交规范1.1 概述1.2 规范1.3 好处二、Commitizen2.1 安装2.2 安装并配置cz-customizable依赖2.2.1 安装依赖2.2.2 配置package.json2.2.3 添加cz-config配置文件2.3 使用2.4 问题一、约定式提交规范 1.1 概述 约定式提交规范是一种基于提交信息的轻量级约…

ES6 入门教程 26 编程风格 26.4 对象 26.5 数组 26.6 函数

ES6 入门教程 ECMAScript 6 入门 作者&#xff1a;阮一峰 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录ES6 入门教程26 编程风格26.4 对象26.5 数组26.6 函数26 编程风格 26.4 对象 单行定义的对象&#xff0c;最后一个成员不以逗号结尾。多…

流媒体传输 - RTSP 协议

概述 协议简介 RTSP RTSP (Real-Time Stream Protocol) 实时流传输协议是一种基于文本的应用层协议&#xff0c;常被用于 建立的控制媒体流的传输&#xff0c;该协议用于 C/S 模型 , 是一个 基于文本 的协议&#xff0c;用于在客户端和服务器端建立和协商实时流会话。 RTP …

JS语句完全攻略

JavaScript 语言定义了 20 套&#xff08;或个&#xff09;语句命令&#xff0c;分别执行不同的操作。 以用途划分&#xff0c;JavaScript 语句可以分为&#xff1a;声明、分支控制、循环控制、流程控制异常处理和其他。 以结构划分&#xff0c;JavaScript 语句又可以分为单句…

【Python】基础知识(语句,函数)

目录Python基础语法接上次的知识点补充顺序语句条件/分支语句语法格式空语句 pass循环语句while 循环For循环continue和break函数语法格式调用函数/使用函数函数参数函数返回值变量作用域函数执行过程链式调用嵌套调用函数递归参数默认值关键字参数写在前面&#x1f34e;&#…

全双工物联网远程控制门禁设计方案

远程控制物联网方案 (此方案成本250元~300元优点是远低于产家报价400&#xff5e;500,使用自家服务器扩展成本低) 组装后连线效果实物图 网关配置 工具见下面产品说明 通讯是TCP/IP协议,一定要配置好服务器地址与网关 通讯是TCP/IP协议,一定要配置好服务器地址与网关 通讯是TCP…

照片人像模糊怎么调?两分钟教会你

有时候我们在拍摄一些照片的时候&#xff0c;可能会因为一些特殊原因而导致照片中的人脸出现模糊的情况&#xff0c;从而使我们无法对照片进行浏览&#xff0c;这时最简单的方法就是借助一些软件来修复模糊的人脸照片&#xff0c;那你们知道如何利用这些软件进行操作吗&#xf…

机器视觉_HALCON_1.了解HALCON

文章目录HALCON概述1. 关于HALCON2. HALCON XL3. 了解HALCON3.1. 通用性说明3.2. 安装HALCON3.3. 继续了解HALCON的第一步4. 更多HALCON资料5. 结语HALCON概述 1. 关于HALCON HALCON是MVTec公司的一款软件产品。 它是一款风靡全球的、用于机器视觉的标准软件&#xff0c;并带…

React - Ant Design3.x版本安装使用,并按需引入和自定义主题

React - Ant Design3.x版本安装使用&#xff0c;并按需引入和自定义主题一. 安装使用 antd二&#xff0e;antd 高级配置安装 react-app-rewired&#xff0c;对 create-react-app 的默认配置进行自定义安装 babel-plugin-import &#xff0c;按需加载组件代码和样式自定义主题An…