首页/新闻资讯/正文详情

Apache ShenYu Wasm 数据同步插件实战:将 Rust 编写的 PluginDataHandler 编译为 wasm 并与 Java 侧集成

发布时间:2026/9/25 3:02:25 来源:云帆数科 栏目:资讯中心
Apache ShenYu Wasm 数据同步插件实战:将 Rust 编写的 PluginDataHandler 编译为 wasm 并与 Java 侧集成
后端API网关微服务【免费下载链接】shenyuApache ShenYu is a Java native API Gateway for service proxy, protocol conversion and API governance.项目地址https://gitcode.com/gh_mirrors/sh/shenyu点击查看免费下载本文以 ShenYu 仓库中shenyu-plugin-wasm-base模块的 Rust 测试样例rust-plugin-data-handler为主体完整讲解该样例的 wasm 文件构建流程安装工具链、cargo build --target wasm32-wasi、产物命名与重命名规则并结合仓库源码剖析 Java 侧如何通过 Wasmtime 加载 wasm、通过shenyu导入模块实现 Rust 与 Java 的双向数据交换。读完本文你可以独立完成一次完整的 “Rust 编写数据处理器 → 编译为 wasm → 以类名规则重命名 → 作为 classpath 资源被 Java 测试加载运行” 的闭环操作。一、这个 README 在整个 wasm 插件体系中处于什么位置ShenYu 对插件的扩展提供了 WebAssembly 支持核心代码集中在两个模块shenyu-plugin-wasm-api提供 WasmLoader 加载器负责定位.wasm文件、实例化模块、把 Java 函数以导入import形式暴露给 wasmshenyu-plugin-wasm-base提供三类AbstractWasm*Handler抽象基类其中 AbstractWasmPluginDataHandler 对应插件、选择器、规则的数据同步回调handlerPlugin/removePlugin/handlerSelector/removeSelector/handlerRule/removeRule。本 README 所在的 rust-plugin-data-handler 目录就是为验证AbstractWasmPluginDataHandler而编写的 Rust 侧配套工程。目录内的文件分工如下文件作用src/lib.rsRust 插件逻辑导出 6 个数据同步回调函数并导入 Java 侧的get_args/put_resultCargo.toml声明crate-type [cdylib]使构建产物为可被 Wasmtime 加载的共享库形态 wasmAbstractWasmPluginDataHandlerTest.javaJava 测试类内部类TestWasmPluginDataHandler继承抽象基类并定义回调到 Java 的函数src/test/resources 下的 .wasm 文件编译并改名后的 wasm 二进制作为 classpath 资源供测试加载二、构建前置安装 Rust 工具链README 给出的前两步是安装 rustup 与 Rust。补充一点实操细节构建命令指定了--target wasm32-wasi而该目标并不随 Rust 默认工具链安装需要通过 rustup 显式添加rustup target add wasm32-wasi这是执行下文构建命令的前提条件README 未展开此步属于构建wasm32-wasi目标的通用要求。三、生成 wasm 文件构建命令与产物路径README 中的核心构建命令为cd {shenyu}/shenyu-plugin/shenyu-plugin-wasm-base/src/test/rust-plugin-data-handler cargo build --target wasm32-wasi --release其中{shenyu}为 ShenYu 仓库根目录的实际路径。构建完成后README 指出产物位于{shenyu}/shenyu-plugin/shenyu-plugin-wasm-base/src/test/rust-plugin-data-handler/target/wasm32-wasi/release/rust_wasm_data_handler_plugin.wasm这里有一个值得注意的源码级事实当前 Cargo.toml 中包名为rust-plugin-data-handler且crate-type为cdylib。按照 Cargo 对 cdylib 的命名约定实际产物文件名应为librust_plugin_data_handler.wasm带lib前缀、连字符转下划线。这说明 README 中记录的rust_wasm_data_handler_plugin.wasm对应的是较早版本包名执行改名步骤时应以target/wasm32-wasi/release/目录下实际生成的.wasm文件为准不要机械照抄旧文件名。四、重命名规则为什么 wasm 文件名必须叫...Test$TestWasmPluginDataHandler.wasmREADME 第 4 步要求把产物重命名为org.apache.shenyu.plugin.wasm.base.handler.AbstractWasmPluginDataHandlerTest$TestWasmPluginDataHandler.wasm这个看似奇怪的命名含$、长得像一个 Java 类名并非随意规定而是由加载器的资源定位逻辑决定的。查看 WasmLoader 构造函数this.wasmName clazz.getName() .wasm; // locate .wasm lib. URL resource clazz.getClassLoader().getResource(wasmName); if (Objects.isNull(resource)) { throw new ShenyuWasmInitException(Cant find wasm file: wasmName); }要点有三文件名 类的全限定名 .wasm。AbstractWasmPluginDataHandler继承WasmLoader并走默认构造this(null, null)此时clazz即当前实例的运行时类——测试中的内部类TestWasmPluginDataHandler。Java 内部类的Class.getName()用$连接外层类名所以得到org.apache.shenyu.plugin.wasm.base.handler.AbstractWasmPluginDataHandlerTest$TestWasmPluginDataHandler这正是 README 要求的目标文件名wasm 文件必须位于 classpath 根路径下。getClassLoader().getResource(wasmName)是按类路径资源查找的因此改名后的.wasm要放到 src/test/resources 目录下随测试 classpath 一起生效。仓库中已存在该文件即为一次构建改名后的入库产物找不到即快速失败抛出ShenyuWasmInitException。如果跳过 README 第 4 步的重命名或放错目录测试会在构造TestWasmPluginDataHandler时直接报 Cant find wasm file 异常这也是该步骤不可省略的原因。同一约定也适用于模块内另外三个 Rust 样例rust-discovery-handler、rust-meta-data-handler、rust-shenyu-wasm-plugin的 README 均采用相同流程且src/test/resources下对应存在四个.wasm资源文件命名均与各自测试的内部类名一一对应。五、源码纵深Rust 与 Java 之间的双向调用协议理解“为什么要构建这个 wasm”需要看懂两侧代码如何配合。5.1 Rust 侧导入 Java 函数 导出 6 个回调lib.rs 开头声明了对外部模块shenyu的导入#[link(wasm_import_module shenyu)] extern C { fn get_args(arg_id: i64, addr: i64, len: i32) - i32; fn put_result(arg_id: i64, addr: i64, len: i32) - i32; }get_args用于从 Java 侧线性内存读取参数如序列化后的 PluginData 内容put_result用于把 Rust 处理结果写回 Java 侧内存。随后通过#[no_mangle]导出 6 个与AbstractWasmPluginDataHandler常量完全对应的回调handlerPlugin、removePlugin、handlerSelector、removeSelector、handlerRule、removeRulelib.rs L38-L72每个回调内部都会调用impls(arg_id)演示一次完整的数据往返。5.2 Java 侧shenyu导入模块由 WasmLoader 统一命名shenyu这个导入模块名在 Java 侧的常量是 WasmLoader 中的IMPORT_WASM_MODULE_NAME shenyu。测试类通过覆写initWasmCallJavaFunc把get_args/put_result两个 Java 闭包注册进wasmCallJavaFuncMap由Linker定义到shenyu模块下。测试中的实现AbstractWasmPluginDataHandlerTest.java L146-L171get_args把字符串hello from java argId逐字节写入 wasm 线性内存通过super.getBuffer()拿到ByteBuffer断言收到的argId为0put_result按地址从线性内存读回字节断言内容为 Rust 写回的rust result。两侧断言互为镜像Java 写hello from java 0Rust 断言读取成功Rust 写rust resultJava 断言读取成功——构成一次端到端的内存交换验证。5.3 参数如何跨越 wasm 边界argId间接寻址模式Wasm 与 Java 之间无法像 JNI 那样直接传对象引用AbstractWasmPluginDataHandler 的 callWASI 因此采用了间接寻址final Long argumentId getPluginArgumentId(pluginData); PLUGIN_ARGUMENTS.put(argumentId, pluginData); WasmFunctions.consumer(super.getStore(), execute.func(), WasmValType.I64) .accept(argumentId); PLUGIN_ARGUMENTS.remove(argumentId);Java 先把PluginData按Long型 ID 存入静态ConcurrentHashMap再向 wasm 函数只传一个 I64 参数wasm 侧拿到 ID 后回调get_args(arg_id, addr, len)Java 闭包凭 ID 从 Map 中取回真实对象并序列化进内存。测试中getPluginArgumentId保持基类默认值0L这正解释了测试里对hello from java 0的断言。六、完整操作清单与验证方式综合 README 与源码一次完整的操作顺序如下# 1. 安装 rustup 与 Rust略按官方方式安装 # 2. 确保 wasm32-wasi 目标已安装 rustup target add wasm32-wasi # 3. 构建{shenyu} 替换为仓库根目录实际路径 cd {shenyu}/shenyu-plugin/shenyu-plugin-wasm-base/src/test/rust-plugin-data-handler cargo build --target wasm32-wasi --release # 4. 将 target/wasm32-wasi/release/ 下实际生成的 .wasm # 重命名为 org.apache.shenyu.plugin.wasm.base.handler.AbstractWasmPluginDataHandlerTest$TestWasmPluginDataHandler.wasm # 并放入 src/test/resources 目录与仓库中已入库的同名文件位置一致随后运行该模块的测试即可触发完整链路mvn test -pl shenyu-plugin/shenyu-plugin-wasm-base验证点测试通过即代表 wasm 加载、shenyu模块导入绑定、6 个回调调用、双向内存交换全部成功由于 WasmLoader 中WasiCtxBuilder().inheritStdout().inheritStderr()继承了标准错误流Rust 侧的eprintln!如rust side- recv:hello from java 0与 Java 侧日志java side-hello from java 0会出现在测试输出中可用于人工确认数据往返方向。七、适用前提与注意事项本文流程针对当前仓库2.7.0-SNAPSHOT 版本线下shenyu-plugin-wasm-base的测试样例shenyu-plugin-wasm-base的 pom.xml 依赖shenyu-plugin-wasm-api与shenyu-plugin-base构建测试前需保证依赖可解析仓库中已提交改名后的.wasm二进制文件若仅运行 Java 测试而无需改动 Rust 代码可跳过构建步骤只有修改了 lib.rs 逻辑后才需要重新执行第二至四节并覆盖src/test/resources下的同名.wasm文件README 中记录的产物文件名与当前 Cargo 包名不一致实际执行时以构建目录中真实生成的文件为准见第三节说明wasm 文件名与类名的绑定关系由WasmLoader的clazz.getName() .wasm约定强制约束若你为自己的测试类新增内部 Handler 类需同步保证资源文件名与其全限定名一致否则会抛出ShenyuWasmInitException。赞分享后端API网关微服务【免费下载链接】shenyuApache ShenYu is a Java native API Gateway for service proxy, protocol conversion and API governance.项目地址https://gitcode.com/gh_mirrors/sh/shenyu点击查看免费下载相关推荐Apache ShenYu Wasm 插件开发构建 Rust 测试 Wasm 文件与 Java 侧加载机制解析Apache ShenYu Wasm 插件开发构建 Rust 测试 Wasm 文件与 Java 侧加载机制解析 本篇技术指南以 shenyu plugin w后端API网关微服务Apache ShenYu Wasm 插件实战编译 Rust 实现的 Discovery Handlerwasm32-wasi 构建与类路径命名规范Apache ShenYu Wasm 插件实战编译 Rust 实现的 Discovery Handlerwasm32 wasi 构建与类路径命名规范 本篇后端API网关微服务Apache DataFusion WebAssembly 实战用 wasm-pack 将 Rust 查询引擎编译到浏览器Apache DataFusion WebAssembly 实战用 wasm pack 将 Rust 查询引擎编译到浏览器 Apache DataFusion大数据数据分析后端上一篇告别复杂API调用Laravel HTTP客户端让外部请求如此简单下一篇Dream GraphQL集成指南构建现代化API服务的完整方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

testssl.sh 预编译 OpenSSL 测试二进制(bin 目录)完全指南:弱加密检测能力、安全边界与实战用法
testssl.sh 预编译 OpenSSL 测试二进制(bin 目录)完全指南:弱加密检测能力、安全边界与实战用法

网络安全应用安全CLI漏洞扫描 【免费下载链接】testssl.sh Testing TLS/SSL encryption anywhere on any port 项目地址: https://gitcode.com/gh_mirrors/te/testssl.sh 点击查看 免费下载 导读 本文围绕 testssl.sh 仓库中 bin/Readme.md 展开,系统… · 2026/9/25 3:02:12

Two.js 核心入口类 Two 全解析:从实例化、渲染类型到场景构建与图形工厂方法
Two.js 核心入口类 Two 全解析:从实例化、渲染类型到场景构建与图形工厂方法

图形学前端 【免费下载链接】two.js A renderer agnostic two-dimensional drawing api for the web 项目地址: https://gitcode.com/gh_mirrors/tw/two.js 点击查看 免费下载 导读 Two 类是 Two.js 的入口点(entrypoint):通过 … · 2026/9/25 3:02:12

PaddleNLP ERNIE-3.5-SE 实践指南:Parallel Transformer 预训练、SFT/LoRA 精调与动态图预测
PaddleNLP ERNIE-3.5-SE 实践指南:Parallel Transformer 预训练、SFT/LoRA 精调与动态图预测

人工智能大模型预训练微调LoRARLHF强化学习分布式训练 【免费下载链接】PaddleNLP Easy-to-use and powerful LLM and SLM library with awesome model zoo. 项目地址: https://gitcode.com/gh_mirrors/pa/PaddleNLP 点击查看 免费下载 ERNIE-3.5-SE 是 PaddleNLP … · 2026/9/25 3:02:12

RocketMQ大消息处理实战:4MB限制排查与优化方案
RocketMQ大消息处理实战:4MB限制排查与优化方案

1. 4MB限制不是传说:客户端和Broker各卡一道,先搞清楚“谁说了算”上周有个同事跑来找我,说线上给下游推送客户画像消息,突然开始报错,后台一看发送端直接抛了MQClientException: message body size over maxMessageSi… · 2026/9/25 3:56:33

OpenShorts AI布局自动决策的秘密:为什么发12帧比发整个视频更聪明(含成本测算)
OpenShorts AI布局自动决策的秘密:为什么发12帧比发整个视频更聪明(含成本测算)

OpenShorts AI布局自动决策的秘密:为什么发12帧比发整个视频更聪明(含成本测算) 【免费下载链接】openshorts Open source AI clip generator: turns long videos into viral 9:16 shorts with AI moment detection, face tracking, subtitle… · 2026/9/25 3:56:27

ipatool:一条命令完成 App Store IPA 下载,旧版本直接拿
ipatool:一条命令完成 App Store IPA 下载,旧版本直接拿

ipatool:一条命令完成 App Store IPA 下载,旧版本直接拿 【免费下载链接】ipatool Command-line tool that allows you to search for iOS, iPadOS, tvOS, visionOS, and macOS apps on the App Store, and download .ipa or macOS .pkg app packages. … · 2026/9/25 3:56:27

二分查找全解析:核心思想、边界处理与PTA函数题实现
二分查找全解析:核心思想、边界处理与PTA函数题实现

二分查找这个算法,很多人觉得自己早就掌握了:不就是“对一个有序数组,每次取中间值比较一下,缩小一半范围”嘛。可实际上,我在带学生和帮朋友排查面试题的几年里,发现二分查找反而是翻车率最高的题目之一。… · 2026/9/25 3:56:26

含碳捕集微网多时间尺度低碳经济调度:改进粒子群算法及Matlab实现
含碳捕集微网多时间尺度低碳经济调度:改进粒子群算法及Matlab实现

做微网调度研究的人这两年普遍有个感受:经济性和低碳性已经不能分开算了。我最早接触这个方向时,模型里就是燃料费加运维费,碳排放最多折算成碳税在目标函数里加一笔。后来意识到一个问题:把碳捕集装置(CCS&#xff09… · 2026/9/25 3:56:20

PilotDeck插件开发完全指南:用plugin.json注册工具、Hook与自定义记忆存储
PilotDeck插件开发完全指南:用plugin.json注册工具、Hook与自定义记忆存储

PilotDeck插件开发完全指南:用plugin.json注册工具、Hook与自定义记忆存储 【免费下载链接】PilotDeck Task-oriented AI Agent productivity platform 项目地址: https://gitcode.com/OpenBMB/PilotDeck PilotDeck 是一个任务导向的 AI Agent 生产力平台&am… · 2026/9/25 3:56:20

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码