mirror of
https://github.com/alibaba/higress.git
synced 2026-02-06 23:21:08 +08:00
Higress Rust Wasm 插件开发框架
介绍
此 SDK 用于使用 Rust 语言开发 Higress 的 Wasm 插件。基于 proxy-wasm-rust-sdk 构建,提供了丰富的开发工具和示例。
特性
- 🚀 高性能: 基于 Rust 和 WebAssembly,提供接近原生的性能
- 🛠️ 易开发: 提供完整的开发框架和丰富的示例
- 🔧 可扩展: 支持自定义配置、规则匹配、HTTP 调用等功能
- 📦 容器化: 支持 Docker 构建和 OCI 镜像发布
- 🧪 测试友好: 内置测试框架和 lint 工具
快速开始
环境要求
- Rust 1.80+
- Docker
- Make
- WASI 目标支持:
rustup target add wasm32-wasip1
重要提示:确保使用 rustup 管理的 Rust 工具链,避免与 Homebrew 安装的 Rust 冲突。如果遇到 WASI 目标问题,请确保:
-
使用 rustup 管理 Rust:
# 安装 rustup(如果还没有) curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh # 安装 WASI 目标 rustup target add wasm32-wasip1 -
确保 shell 配置正确:
# 检查 ~/.zshrc 或 ~/.bashrc 是否包含 source "$HOME/.cargo/env"
构建插件
执行路径: 在 plugins/wasm-rust/ 目录下执行
# 进入项目目录
cd plugins/wasm-rust/
# 构建默认插件 (say-hello)
make build
# 构建指定插件
make build PLUGIN_NAME=say-hello
# 构建并指定版本
make build PLUGIN_NAME=say-hello PLUGIN_VERSION=1.0.0
# 注意:由于 Makefile 中的 .DEFAULT 目标,需要明确指定目标
# 如果遇到 "Nothing to be done" 错误,请确保使用正确的语法
重要提示:
- 某些插件(如
ai-data-masking)依赖 C 库,可能需要额外的配置才能成功构建 - 建议先使用简单的插件(如
say-hello)测试构建环境 - 构建成功后会生成
extensions/<plugin-name>/plugin.wasm文件
运行测试
执行路径: 在 plugins/wasm-rust/ 目录下执行
# 进入项目目录
cd plugins/wasm-rust/
# 运行所有测试
make test-base
# 运行指定插件测试
make test PLUGIN_NAME=say-hello
代码检查
执行路径: 在 plugins/wasm-rust/ 目录下执行
# 进入项目目录
cd plugins/wasm-rust/
# 运行所有 lint 检查
make lint-base
# 运行指定插件 lint 检查
make lint PLUGIN_NAME=say-hello
Makefile 说明
当前 Makefile 包含以下可用目标:
build- 构建插件(默认插件为 say-hello)build-image- 构建插件对应镜像(默认插件为 say-hello)lint-base- 对所有代码进行 lint 检查lint- 对指定插件进行 lint 检查test-base- 运行所有测试test- 运行指定插件测试builder- 构建构建器镜像
重要提示:Makefile 中的 .DEFAULT: 目标可能会影响某些命令的执行。如果遇到 "Nothing to be done" 错误,请确保:
- 正确指定了目标名称(如
build、lint、test) - 使用了正确的参数格式
- 插件目录存在且包含有效的 Cargo.toml 文件
插件开发
项目结构
wasm-rust/
├── src/ # SDK 核心代码
│ ├── cluster_wrapper.rs # 集群包装器
│ ├── error.rs # 错误处理
│ ├── event_stream.rs # 事件流处理
│ ├── internal.rs # 内部 API
│ ├── log.rs # 日志系统
│ ├── plugin_wrapper.rs # 插件包装器
│ ├── redis_wrapper.rs # Redis 包装器
│ ├── request_wrapper.rs # 请求包装器
│ └── rule_matcher.rs # 规则匹配器
├── extensions/ # 插件示例
│ ├── say-hello/ # 基础示例
│ ├── ai-data-masking/ # AI 数据脱敏
│ ├── request-block/ # 请求拦截
│ ├── ai-intent/ # AI 意图识别
│ └── demo-wasm/ # 演示插件
├── example/ # 完整示例
│ ├── wrapper-say-hello/ # 包装器示例
│ └── sse-timing/ # SSE 时序示例
└── Makefile # 构建脚本
创建新插件
执行路径: 在 plugins/wasm-rust/ 目录下执行
- 创建插件目录
# 进入项目目录
cd plugins/wasm-rust/
# 创建插件目录
mkdir extensions/my-plugin
cd extensions/my-plugin
- 创建 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 = { git="https://github.com/higress-group/proxy-wasm-rust-sdk", branch="main", version="0.2.2" }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
- 创建插件代码
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: SharedRuleMatcher<MyPluginConfig>,
}
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) -> Option<Box<dyn HttpContext>> {
Some(Box::new(MyPlugin {
log: self.log.clone(),
rule_matcher: self.rule_matcher.clone(),
}))
}
fn get_type(&self) -> Option<ContextType> {
Some(ContextType::HttpFilter)
}
}
struct MyPlugin {
log: Log,
rule_matcher: SharedRuleMatcher<MyPluginConfig>,
}
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! {|_| -> Box<dyn RootContext> {
Box::new(MyPluginRoot::new())
}}
插件配置
插件支持全局配置和规则配置:
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"
内置插件
基础插件
- say-hello: 基础示例插件,演示插件开发流程 ✅
- demo-wasm: 完整演示插件,包含 Redis 集成等功能
功能插件
-
ai-data-masking: AI 数据脱敏插件 ⚠️
- 支持敏感词拦截和替换
- 支持 OpenAI 协议和自定义 JSONPath
- 内置敏感词库和自定义规则
- 注意: 依赖 C 库,可能需要额外配置
-
request-block: 请求拦截插件 ✅
- 支持 URL、Header、Body 拦截
- 支持正则表达式匹配
- 可配置拦截状态码和消息
-
ai-intent: AI 意图识别插件
- 支持 LLM 调用和意图分类
- 可配置代理服务和模型参数
构建状态说明:
- ✅ 已验证可成功构建
- ⚠️ 可能需要额外配置
- 未标记的插件需要进一步测试
故障排除
问题: error[E0463]: can't find crate for 'core'
原因: 系统中有多个 Rust 安装,Homebrew 的 Rust 优先于 rustup 的 Rust
解决方案:
# 移除 Homebrew 的 Rust
brew uninstall rust
# 确保使用 rustup 的 Rust
rustup default nightly
rustup target add wasm32-wasip1
# 确保 shell 配置正确
echo 'source "$HOME/.cargo/env"' >> ~/.zshrc
source ~/.zshrc
构建和部署
本地构建
执行路径: 在 plugins/wasm-rust/ 目录下执行
# 进入项目目录
cd plugins/wasm-rust/
# 使用 Makefile 构建插件(推荐)
make build PLUGIN_NAME=my-plugin
# 直接使用 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_NAME=my-plugin .
### Docker 构建说明
**重要提示**:Dockerfile 需要指定 `PLUGIN_NAME` 参数来构建特定插件。
```bash
# 构建 say-hello 插件
docker build -t say-hello:latest --build-arg PLUGIN_NAME=say-hello .
# 构建 ai-data-masking 插件
docker build -t ai-data-masking:latest --build-arg PLUGIN_NAME=ai-data-masking .
# 构建 request-block 插件
docker build -t request-block:latest --build-arg PLUGIN_NAME=request-block .
# 构建自定义插件
docker build -t my-custom-plugin:latest --build-arg PLUGIN_NAME=my-custom-plugin .
```
**插件分发特性**:
- 遵循OCI镜像规范的插件分发,可以参考[OCI镜像规范](https://github.com/opencontainers/image-spec/blob/main/image-layout.md)
- 基于 `rust:1.80` 构建环境
- 自动安装 WASI 目标
- 多阶段构建,最终镜像基于 `scratch`
- 最小化镜像大小(约 300-400KB)
- 只包含编译后的 WASM 文件
**常见问题**:
- **错误**: `failed to read dockerfile: open Dockerfile: no such file or directory`
- **解决**: 确保在 `plugins/wasm-rust/` 目录下执行命令
- **错误**: `failed to solve: failed to compute cache key`
- **解决**: 确保指定了正确的 `PLUGIN_NAME` 参数
- **错误**: `can't find crate for 'core'`
- **解决**: Docker 构建环境会自动安装 WASI 目标,无需手动配置
### 发布到镜像仓库
**执行路径**: 在 `plugins/wasm-rust/` 目录下执行
```bash
# 进入项目目录
cd plugins/wasm-rust/
# 构建插件
make build PLUGIN_NAME=my-plugin PLUGIN_VERSION=1.0.0
# 构建构建器镜像
make builder
在 Higress 中使用
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.0
开发工具
路径说明
不同命令需要在不同的目录下执行:
- Makefile 命令(如
make build、make build-image、make test、make lint):在plugins/wasm-rust/目录下执行 - Cargo 命令(如
cargo build、cargo test):在具体的插件目录下执行(如plugins/wasm-rust/extensions/my-plugin/) - Docker 命令:在
plugins/wasm-rust/目录下执行,需要指定PLUGIN_NAME参数
调试
插件支持详细的日志输出:
self.log.info("Processing request");
self.log.debugf(format_args!("Request headers: {:?}", headers));
self.log.error("Error occurred");
测试
执行路径: 在插件目录下执行(如 plugins/wasm-rust/extensions/my-plugin/)
# 进入插件目录
cd plugins/wasm-rust/extensions/my-plugin/
# 运行单元测试
cargo test
# 运行集成测试
cargo test --test integration
性能优化
- 使用
--release模式构建 - 避免不必要的内存分配
- 合理使用缓存机制
贡献指南
- Fork 项目
- 创建功能分支
- 提交代码变更
- 运行测试和 lint 检查
- 提交 Pull Request
相关链接
许可证
本项目采用 Apache 2.0 许可证。