ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Higress Rust Wasm 插件开发指南:基于 WebAssembly 的高性能 AI 网关扩展实践

Higress Rust Wasm 插件开发指南:基于 WebAssembly 的高性能 AI 网关扩展实践 Higress Rust Wasm 插件开发指南基于 WebAssembly 的高性能 AI 网关扩展实践【免费下载链接】higress AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higressHigress 是基于 Envoy 与 Istio 构建的 AI 原生 API 网关而 Rust Wasm 插件是其高性能扩展能力的重要载体插件以 WebAssembly 形式运行在网关数据面可完成请求拦截、敏感词脱敏、规则路由、Redis 集成等逻辑同时保持接近原生的执行性能。本文以plugins/wasm-rust/目录下的官方 Rust SDK 为主线完整讲解环境搭建、插件构建、规则匹配配置、WasmPlugin 部署以及正式插件与示例插件的实现细节读者阅读后可独立完成一个可构建、可测试、可发布为 OCI 镜像的 Higress Rust 插件。一、框架概述Higress Rust Wasm 插件 SDK1.1 SDK 定位与设计目标plugins/wasm-rust/是 Higress 面向 Rust 语言开发者提供的 Wasm 插件开发 SDK其核心依赖是proxy-wasm-rust-sdkproxy-wasm ABI 的 Rust 绑定并在此基础上封装了日志、规则匹配、HTTP 调用、Redis 访问、事件流处理等网关插件高频能力最终通过proxy_wasm::main!宏生成 Envoy WASM 虚拟机可直接加载的plugin.wasm。SDK 宣称的五大特性对应了网关插件开发的核心诉求高性能基于 Rust 与 WebAssembly代码以接近原生速度执行适合部署在请求热路径上易开发提供完整的开发框架RootContext / HttpContext 生命周期封装与丰富的参考示例可扩展支持自定义配置、规则匹配域名/路由/服务/路由前缀、HTTP 调用、Redis 集成容器化通过 Docker 多阶段构建产出 OCI 镜像可直接被 Higress WasmPlugin CRD 拉取测试友好内置cargo test单元测试与cargo clippy/cargo fmtlint 工具链。从源码结构看SDK 核心库higress-wasm-rust的依赖定义在 plugins/wasm-rust/Cargo.toml 中除proxy-wasm外还引入了serde/serde_json配置反序列化、multimap多值请求头、httpHTTP 类型、lazy_static静态变量、downcast-rs类型向下转换以及关闭默认特性的redis客户端可见 SDK 面向的是网关插件的通用场景组合。1.2 插件生命周期与运行模型一个 Higress Wasm 插件本质上是一个实现 proxy-wasm ABI 的 Envoy HTTP Filter。SDK 将其抽象为两层 ContextRootContext根上下文插件加载时创建一次负责读取并解析插件配置、创建 HTTP 上下文对应on_configure回调HttpContext请求上下文每个 HTTP 请求独立创建负责在请求/响应头、请求/响应体等阶段执行插件逻辑对应on_http_request_headers、on_http_response_headers等回调。SDK 在 src/lib.rs 中按模块对外暴露能力log日志、rule_matcher规则匹配、cluster_wrapper集群信息、request_wrapper请求封装、redis_wrapperRedis 客户端、event_stream事件流用于 SSE 流式响应处理、plugin_wrapperContext 的简化包装器与error错误类型。二、环境准备rustup、WASI 目标与 Docker2.1 最低环境要求依赖版本/说明Rust1.80Docker 构建镜像基于rust:1.80Docker支持 BuildKitDOCKER_BUILDKIT1Make执行make build等目标WASI 目标rustup target add wasm32-wasip12.2 使用 rustup 管理 Rust 工具链README 特别强调必须使用 rustup 管理的 Rust 工具链避免与 Homebrew 安装的 Rust 冲突。若系统同时存在两套 Rustcargo可能解析到 Homebrew 版本而缺少 WASI 标准库进而报出error[E0463]: cant find crate for core。# 安装 rustup如果还没有 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh # 安装 WASI 目标 rustup target add wasm32-wasip1同时确保 shell 配置文件~/.zshrc或~/.bashrc中已加入 rustup 环境变量source $HOME/.cargo/env2.3 常见故障排除error[E0463]该错误的根因是系统存在多个 Rust 安装且 Homebrew 版本优先级更高解决方案如下# 移除 Homebrew 的 Rust brew uninstall rust # 确保使用 rustup 的 Rust rustup default nightly rustup target add wasm32-wasip1 # 确保 shell 配置正确 echo source $HOME/.cargo/env ~/.zshrc source ~/.zshrc三、快速开始构建、测试与代码检查3.1 构建插件所有 Makefile 命令均在plugins/wasm-rust/目录下执行cd plugins/wasm-rust/ # 构建默认的正式插件ai-data-masking make build # 构建示例插件 make build PLUGIN_ROOTexample PLUGIN_NAMEsay-hello # 构建示例插件并指定版本 make build PLUGIN_ROOTexample PLUGIN_NAMEsay-hello PLUGIN_VERSION1.0.0构建成功后会在所选PLUGIN_ROOT下生成plugin-name/plugin.wasm文件。例如make build PLUGIN_ROOTexample PLUGIN_NAMEsay-hello产出plugins/wasm-rust/example/say-hello/plugin.wasm。3.2 运行测试# 运行所有测试SDK 核心库单元测试 make test-base # 运行指定插件测试 make test PLUGIN_ROOTexample PLUGIN_NAMEsay-hello3.3 代码检查# 对所有代码进行 lint 检查cargo fmt cargo clippy make lint-base # 对指定插件进行 lint 检查 make lint PLUGIN_ROOTexample PLUGIN_NAMEsay-hello3.4 Makefile 目标详解当前 Makefile 提供的目标及默认参数如下目标作用关键参数/默认值build构建插件输出 wasm 文件PLUGIN_NAMEai-data-maskingPLUGIN_ROOTextensionsbuild-image构建插件 OCI 镜像额外支持BUILDER指定构建器镜像lint-base全量cargo fmt --checkcargo clippy—lint指定插件 lintPLUGIN_ROOT/PLUGIN_NAMEtest-baseSDK 核心库cargo test --lib—test指定插件测试PLUGIN_ROOT/PLUGIN_NAMEbuilder构建 Wasm 构建器镜像RUST_VERSION1.82、ORAS_VERSION1.0.0此外 Makefile 中还有一组镜像相关变量BUILDER_REGISTRY与REGISTRY默认指向higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/HIGRESS_VERSION默认1.0.0-rc未指定PLUGIN_VERSION时镜像 tag 自动取构建时间戳-短commit idIMAGE_TAG $(if $(strip $(PLUGIN_VERSION)),${PLUGIN_VERSION},${BUILD_TIME}-${COMMIT_ID})便于每次构建生成可追溯的镜像版本。重要提示由于 Makefile 中声明了.DEFAULT:目标若命令未正确指定目标名或参数可能遇到 Nothing to be done 错误。排查要点① 正确指定目标名称如build、lint、test② 使用正确的参数格式③ 插件目录存在且包含有效的Cargo.toml文件。3.5 不同命令的执行路径Makefile 命令make build、make build-image、make test、make lint在plugins/wasm-rust/目录下执行Cargo 命令cargo build、cargo test在具体插件目录下执行例如plugins/wasm-rust/extensions/my-plugin/或plugins/wasm-rust/example/say-hello/Docker 命令在plugins/wasm-rust/目录下执行必须指定PLUGIN_NAME构建example/下的参考插件时还需指定PLUGIN_ROOTexample。四、SDK 核心模块从源码看封装原理4.1 模块总览plugins/wasm-rust/ ├── src/ # SDK 核心代码 │ ├── cluster_wrapper.rs # 集群包装器 │ ├── error.rs # 错误处理 │ ├── event_stream.rs # 事件流处理SSE 等流式场景 │ ├── internal.rs # 内部 API封装 proxy_wasm hostcalls │ ├── log.rs # 日志系统 │ ├── plugin_wrapper.rs # 插件包装器简化 Context 实现 │ ├── redis_wrapper.rs # Redis 包装器 │ ├── request_wrapper.rs # 请求包装器 │ └── rule_matcher.rs # 规则匹配器 ├── extensions/ # 正式发布的 Rust 插件 │ └── ai-data-masking/ # AI 数据脱敏 ├── example/ # 不参与正式发布的参考实现和开发示例 │ ├── ai-intent/ # AI 意图识别 │ ├── demo-wasm/ # 演示插件 │ ├── request-block/ # 请求拦截参考实现 │ ├── say-hello/ # 基础示例 │ ├── wrapper-say-hello/ # 包装器示例 │ └── sse-timing/ # SSE 时序示例 └── Makefile # 构建脚本4.2 日志系统log.rs日志模块在 src/log.rs 中实现Log::new(plugin_name)创建带插件名前缀的日志器底层通过hostcalls::log输出到 Envoy 日志日志输出格式为[plugin_name] message。接口同时提供简单版与格式化版self.log.info(Processing request); self.log.debugf(format_args!(Request headers: {:?}, headers)); self.log.error(Error occurred);支持trace/debug/info/warn/error/critical六个级别以及对应的*f格式化变体tracef、debugf、infof、warnf、errorf、criticalf。格式化变体在调用前会先通过get_log_level判断级别低于当前日志级别时直接返回避免无谓的格式化开销。4.3 规则匹配器rule_matcher.rs全局配置与按规则配置规则匹配是 SDK 最核心的封装实现在 src/rule_matcher.rs它将 Higress WasmPlugin 的defaultConfig与rules语义映射为插件内的全局配置 匹配规则并支持四种匹配维度源码中对应常量定义在 L41-45配置键匹配维度说明_match_route_路由精确匹配路由名route_name_match_domain_域名支持前缀/后缀/精确三种通配_match_service_服务匹配目标服务 FQDN可带端口_match_route_prefix_路由前缀路由名以指定前缀开头即命中parse_rule_configL84-170负责把 JSON 配置解析为global_config与rule_config列表get_match_configL172-217在请求阶段依据当前请求的:authorityHost、route_name、cluster_name依次尝试规则命中未命中任何规则时回退到全局配置。注意源码规定每条规则中四种匹配键只能出现一种否则返回错误there is only one of match_route, match_domain, match_service and match_route_prefix can present in configuration.。域名匹配parse_host_match_configL251-274支持三种通配写法以*开头表示后缀匹配如*.example.com、以*结尾表示前缀匹配如www.*、无*表示精确匹配如www.abc.com*单独出现表示匹配任意域名且对带端口的 Host 自动剥离端口参考 Envoy 的实现逻辑strip_port_from_hostL275-287。SDK 还在 src/rule_matcher.rs 的测试模块L354-737中提供了完整的单元测试覆盖包括test_host_match前缀/后缀/精确/带端口/任意匹配、test_service_matchFQDN 与带端口服务匹配、test_parse_rule_config非法规则校验、四种匹配维度解析以及test_parse_override_config规则配置对全局配置的覆盖合并。这些测试既可作为 SDK 正确性的保障也可作为自定义插件编写测试的参考模板。4.4 配置解析入口on_configureon_configure函数L324-352是插件的统一配置入口从get_plugin_configuration()读取配置字节反序列化为serde_json::Value后交给RuleMatcher::parse_rule_config解析。任何插件只需在RootContext::on_configure中调用它即可获得完整的全局配置 规则匹配能力参考 example/say-hello/src/lib.rs 的用法。五、插件开发实战从零创建一个 Rust 插件5.1 创建插件目录cd plugins/wasm-rust/ mkdir extensions/my-plugin cd extensions/my-plugin5.2 创建 Cargo.toml[package] name my-plugin version 0.1.0 edition 2021 publish false [lib] crate-type [cdylib] [dependencies] higress-wasm-rust { path ../../, version 0.1.0 } proxy-wasm { githttps://github.com/higress-group/proxy-wasm-rust-sdk, branchmain, version0.2.2 } serde { version 1.0, features [derive] } serde_json 1.0两个关键点crate-type [cdylib]是编译为 WASM 动态库的必要条件higress-wasm-rust通过path ../../直接引用仓库内 SDK 源码即上一层的plugins/wasm-rust/目录其 Cargo.toml 中[package] name higress-wasm-rust。5.3 编写插件代码use higress_wasm_rust::*; use proxy_wasm::traits::*; use proxy_wasm::types::*; use serde::{Deserialize, Serialize}; #[derive(Default, Clone, Serialize, Deserialize)] struct MyPluginConfig { name: String, } struct MyPluginRoot { log: Log, rule_matcher: SharedRuleMatcherMyPluginConfig, } impl MyPluginRoot { fn new() - Self { Self { log: Log::new(my-plugin.to_string()), rule_matcher: Rc::new(RefCell::new(RuleMatcher::new())), } } } impl Context for MyPluginRoot {} impl RootContext for MyPluginRoot { fn on_configure(mut self, plugin_configuration_size: usize) - bool { on_configure(self, plugin_configuration_size, mut self.rule_matcher.borrow_mut(), self.log) } fn create_http_context(self, context_id: u32) - OptionBoxdyn HttpContext { Some(Box::new(MyPlugin { log: self.log.clone(), rule_matcher: self.rule_matcher.clone(), })) } fn get_type(self) - OptionContextType { Some(ContextType::HttpFilter) } } struct MyPlugin { log: Log, rule_matcher: SharedRuleMatcherMyPluginConfig, } impl Context for MyPlugin {} impl HttpContext for MyPlugin { fn on_http_request_headers(mut self, _num_headers: usize, _end_of_stream: bool) - HeaderAction { self.log.info(Processing request headers); HeaderAction::Continue } } proxy_wasm::main! {|_| - Boxdyn RootContext { Box::new(MyPluginRoot::new()) }}SharedRuleMatcherPluginConfig是RcRefCellRuleMatcherPluginConfig的类型别名见 src/rule_matcher.rsRoot 与 Http 两个 Context 通过Rc共享同一份配置保证配置只解析一次、请求阶段只读匹配。5.4 简化写法使用插件包装器plugin_wrapper参考实现 example/request-block/src/lib.rs 展示了更简洁的写法通过RootContextWrapper/HttpContextWrapperSDK 的 src/plugin_wrapper.rs实现create_http_context_use_wrapper与on_http_request_complete_headers等回调框架自动完成按规则匹配到配置 → 注入on_config→ 调用业务回调的流程开发者只需关注on_config拿到当前请求应使用的配置和业务钩子函数即可。六、插件配置WasmPlugin 中的全局配置与规则配置插件支持全局配置和规则配置。以 Higress 的WasmPluginCRD 为例defaultConfig是全局默认配置rules[].config是路由/域名级别的规则配置SDK 内部的_match_*键由 Higress 控制面从rules[].match自动注入apiVersion: extensions.higress.io/v1alpha1 kind: WasmPlugin metadata: name: my-plugin namespace: higress-system spec: selector: matchLabels: higress: higress-system-higress-gateway defaultConfig: name: default url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/my-plugin:1.0.0 rules: - match: - route: - my-route config: name: route-specific上述配置含义所有请求默认使用{name: default}作为全局配置当请求命中路由my-route时SDK 的get_match_config返回{name: route-specific}。参考 example/say-hello/envoy.yaml 可以看到在纯 Envoy 环境无控制面下手写等价配置的方式configuration中直接写_rules_数组每条规则使用_match_domain_/_match_route_等 SDK 原生键。值得注意的匹配规则细节均有源码与单元测试佐证域名支持通配*.example.com后缀、www.*前缀、*任意、www.abc.com精确请求 Host 带端口时自动剥离端口参与匹配路由前缀匹配基于route_name.starts_with(prefix)服务匹配基于cluster_name的outbound|port||fqdn四段式结构配置中可写fqdn或fqdn:port两种形式见 src/rule_matcher.rs 的service_match与 测试用例。七、正式插件与示例插件extensions/仅包含参与正式构建和发布的插件example/中的实现用于开发参考不参与正式插件发布。7.1 示例插件say-hello✅ 已验证可构建基础示例插件演示完整插件开发流程。核心逻辑在 example/say-hello/src/lib.rs在on_http_request_headers中通过rule_matcher.get_match_config()获取当前请求配置直接返回Hello, {name}!响应。配套的 envoy.yaml 与docker-compose.yaml可在纯 Envoy 环境本地联调。demo-wasm完整演示插件包含 Redis 集成等功能。7.2 正式插件ai-data-masking⚠️ 依赖 C 库可能需要额外配置AI 数据脱敏插件支持敏感词拦截和替换、OpenAI 协议和自定义 JSONPath、内置敏感词库和自定义规则。详细配置见其 README运行属性为执行阶段认证阶段、执行优先级991。7.3 其他参考实现request-block✅ 已验证可构建请求拦截插件支持 URL、Header、Body 拦截支持正则表达式匹配可配置拦截状态码和消息。配置结构见 example/request-block/src/lib.rsblocked_code默认 403、blocked_message、case_sensitive默认 true、block_urlsURL 包含匹配、block_exact_urlsURL 精确匹配、block_regexp_urls正则匹配、block_headers请求头匹配、block_bodies请求体匹配当配置了block_bodies时框架会自动缓存请求体cache_request_body返回 true。ai-intentAI 意图识别插件支持 LLM 调用和意图分类可配置代理服务和模型参数。构建状态说明✅ 表示已验证可成功构建⚠️ 表示可能需要额外配置未标记的插件需要进一步测试。八、构建与部署从 WASM 文件到 OCI 镜像8.1 本地构建# 进入项目目录 cd plugins/wasm-rust/ # 使用 Makefile 构建正式插件推荐 make build PLUGIN_NAMEmy-plugin # 构建 example/ 下的参考插件 make build PLUGIN_ROOTexample PLUGIN_NAMEsay-hello # 直接使用 Cargo 构建 WASM 文件 cd extensions/my-plugin cargo build --target wasm32-wasip1 --release # 构建 Docker 镜像 cd plugins/wasm-rust/ docker build -t my-plugin:latest --build-arg PLUGIN_NAMEmy-plugin .8.2 Docker 构建说明重要提示Dockerfile 需要指定PLUGIN_NAME参数来构建特定插件。# 构建 say-hello 示例插件 docker build -t say-hello:latest --build-arg PLUGIN_ROOTexample --build-arg PLUGIN_NAMEsay-hello . # 构建 ai-data-masking 插件 docker build -t ai-data-masking:latest --build-arg PLUGIN_NAMEai-data-masking . # 构建 request-block 参考插件 docker build -t request-block:latest --build-arg PLUGIN_ROOTexample --build-arg PLUGIN_NAMErequest-block . # 构建自定义插件 docker build -t my-custom-plugin:latest --build-arg PLUGIN_NAMEmy-custom-plugin .Dockerfile 采用两阶段构建builder 阶段基于rust:1.80自动执行rustup target add wasm32-wasip1安装 WASI 目标支持PLUGIN_NAME默认ai-data-masking、PLUGIN_ROOT默认extensions、BUILD_OPTS默认--release、PREBUILD默认.prebuild四个构建参数若插件目录中存在.prebuild脚本会先执行用于处理 C 库等额外依赖随后cargo build --target wasm32-wasip1 --release并拷贝 wasm 产物output 阶段基于scratch仅保留plugin.wasm文件。插件分发遵循 OCI 镜像规范镜像体积被压缩到约 300-400KB只包含编译后的 WASM 文件可直接被 Higress 控制面拉取注入网关。常见问题错误failed to read dockerfile: open Dockerfile: no such file or directory→ 确保在plugins/wasm-rust/目录下执行命令错误failed to solve: failed to compute cache key→ 确保指定了正确的PLUGIN_NAME参数错误cant find crate for core→ Docker 构建环境会自动安装 WASI 目标无需手动配置。8.3 发布到镜像仓库# 进入项目目录 cd plugins/wasm-rust/ # 构建插件 make build PLUGIN_NAMEmy-plugin PLUGIN_VERSION1.0.0 # 构建构建器镜像 make buildermake builder通过 DockerfileBuilder 生成统一的构建器镜像可定制RUST_VERSION、ORAS_VERSION、HIGRESS_VERSION之后make build-image可复用该构建器保证 CI 环境与本地构建行为一致。8.4 在 Higress 中使用构建并推送到镜像仓库后通过 WasmPlugin CRD 将插件挂载到网关apiVersion: extensions.higress.io/v1alpha1 kind: WasmPlugin metadata: name: my-plugin namespace: higress-system spec: selector: matchLabels: higress: higress-system-higress-gateway defaultConfig: # 插件配置 url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/my-plugin:1.0.0Higress 控制面会从oci://地址拉取镜像中的plugin.wasm注入到被selector选中的网关实例并按defaultConfig/rules生成 SDK 可解析的插件配置。九、调试、测试与性能优化9.1 日志调试插件支持详细的分级日志输出建议在开发期将日志级别调至 Trace参考 example/say-hello/src/lib.rs 中proxy_wasm::set_log_level(LogLevel::Trace)通过网关日志观察插件行为self.log.info(Processing request); self.log.debugf(format_args!(Request headers: {:?}, headers)); self.log.error(Error occurred);9.2 单元测试与集成测试# 进入插件目录 cd plugins/wasm-rust/extensions/my-plugin/ # 运行单元测试 cargo test # 运行集成测试 cargo test --test integrationmake test-base会执行 SDK 核心库higress-wasm-rust的全部单元测试其中rule_matcher的测试套件覆盖了配置解析、四种匹配维度与配置覆盖合并等关键路径可作为自定义插件测试的样板。9.3 性能优化建议使用--release模式构建Makefile 的build与 Dockerfile 默认均已启用--release避免不必要的内存分配尽量复用已解析的配置RuleMatcher在 RootContext 中只解析一次请求阶段通过Rc共享合理使用缓存机制如 request-block 仅在配置了block_bodies时才缓存请求体避免无谓开销。十、贡献指南参与plugins/wasm-rust的插件开发流程Fork 项目创建功能分支提交代码变更运行测试和 lint 检查make test-base、make lint-base或针对插件的make test/make lint提交 Pull Request。十一、总结Higress 的 Rust Wasm 插件 SDKplugins/wasm-rust/将 proxy-wasm ABI 封装为一套开箱即用的插件开发框架rule_matcher统一了全局配置 规则配置的解析与请求期匹配log/redis_wrapper/event_stream等模块覆盖网关插件的高频能力Makefile 与多阶段 Dockerfile 打通了从源码到 OCI 镜像的完整发布链路。配合 Higress 的WasmPluginCRD开发者可以用 Rust 编写高性能、可规则化配置的网关扩展并通过extensions/与example/中的正式插件、参考实现加速自己的插件开发。【免费下载链接】higress AI Gateway | AI Native API Gateway项目地址: https://gitcode.com/GitHub_Trending/hi/higress创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表