前言
再厉害的大佬,也不可能掌握所有的编程语言。那如何让所有人都能用自己喜欢的语言编写规则那?
我的选择是wasm,通过提供wasm运行时,用任意语言运行规则。
WASM Runtime
和之前的lua runtime 实现是类似的。和ruch_core并不强绑定,并提供rush_core
这个feature进行关联。核心实现代码地址
支持同步和异步运行。
先看性能测试
wasm_async_flow time: [8.7260 µs 8.8046 µs 8.8806 µs]
编写一个wasm脚本
我这里直接用rust写一个脚本。内容很简单,导入两个函数,并将输入的内容拼接在input上进行回显。
- success 函数 : 用来设置成功时的返回值
- error 函数: 用来返回一个错误
- 源代码链接
extern "C" {
fn success(ptr: *const u8, len: usize) -> u32;
fn error(ptr: *const u8, len: usize) -> u32;
}
#[no_mangle]
pub extern "C" fn handle(ptr: *mut c_char, len: u32) -> u32 {
unsafe {
let slice = std::slice::from_raw_parts(ptr, len as usize);
let cs = CStr::from_ptr(slice.as_ptr());
let cs = CString::from(cs);
let s = cs.to_str().unwrap();
let s = format!(r#"{{"input":{}}}"#, s);
success(s.as_ptr(), s.len());
}
1u32
}
运行命令cargo build --target wasm32-unknown-unknown --release
编译一个wasm文件,名字:wasm_example_one.wasm
。
我这里已经编译了一个现成的包,可以直接下载使用
调用这个包
仍然按照我们之前的约定,编写一个规则,指明引擎和文件位置,然后调用上面的wasm规则。
const WASM_RULE: &'static str = "
rule WASM_RULE _ wasm
wasm_file: wasm_example/wasm_example_one.wasm
";
#[tokio::test]
async fn test_wasm_build() {
let rt = WasmRuntimeFactory::new()
.async_build(WASM_RULE)
.await
.unwrap();
let result: HashMap<String, String> =
rt.async_flow(Value::String("hello".into())).await.unwrap();
assert_eq!(result.get("input").unwrap().as_str(), "hello");
}
自定义解析
和lua runtime一样,生产上并不一定从文件中解析规则,往往是从远程拉取,所以提供了自定义解析脚本的抽象。只需要实现这个trait,并注册到 WasmRuntimeFactory
中。
#[async_trait::async_trait]
pub trait WasmLoader: Send + Sync {
fn load(&self, _rule_name: String, file: String) -> anyhow::Result<Vec<u8>>;
async fn async_load(&self, rule_name: String, file: String) -> anyhow::Result<Vec<u8>> {
self.load(rule_name, file)
}
}
尾语
细心地朋友肯定发现了,对wasm并没有提供类似expr和lua的环境变量的支持。这个主要是因为wasm基本已经脱离了书写规则的范畴,再进行统一的环境变量管理已经不合时宜,并且对后续的wasm维护存在影响。
虽然说wasm是多语言通用的,但目前仍然局限在浏览器上,而脱离浏览器的wasi目前看起来并不成熟。像我们之前的博文中体验了go语言wasip1,明显还是个半成品,其他语言的支持看起来遥遥无期。
但是,wasi的性能是远远超过目前wasm的,允许异步 允许多线程运行,并且脱离了浏览器。按照目前的计划,rush对wasm的支持最终会升级成wasi。而wasi已经类似于docker这种,形成了容器式的运行环境,解释了前面为什么不会提供类似expr和lua侵入式的环境变量。
目前已经将rush推送了crates.io中,对应的包名称和地址
包名称 | 地址 | 备注 |
---|---|---|
rush_core | crates.io/crates/rush… | 核心抽象 |
rush_expr_engine | crates.io/crates/rush… | 表达式引擎,和rush_core强绑定 |
rush_lua_engine | crates.io/crates/rush… | lua引擎,和rush_core弱绑定 |
rush_wasm_engine | crates.io/crates/rush… | wasm引擎,和rush_core弱绑定 |