1. 为什么是 Rust + WASM
n8n 的自托管体验已经证明:低代码连线 + 无限节点是开发者最愿意买单的自动化形态。但它基于 Node.js 的架构让冷启动停留在 3–5 s,镜像体积 400 MB 起步,且插件需要 NPM 安装重启,无法在线热插拔。
Rust 编译到 WebAssembly 能把冷启动压到 <200 ms,单节点体积 <1 MB;同时 WASM 的沙盒与 capability 模型让「下载就能运行」的节点市场真正安全。Sim 引擎就是把这两张王牌组合成 Apache-2.0 的自托管方案:内核用 Rust 做调度与数据总线,业务逻辑全部下沉到 WASM 插件,节点级弹性伸缩直接复用 Kubernetes 的 Pod 自动扩缩容语义。
2. 架构总览:三进程 + 两队列
- sim-server:Rust 写的控制面,暴露 REST/WS 接口,负责 DSL 解析、状态机转换、秘密存储。
- sim-runtime:WASM 运行时进程池,基于 wasmer 2.x,单进程可托管 1 000+ 节点实例;通过 Unix Domain Socket 与 server 通信,支持 capability 白名单 + 内存限额。
- sim-worker:可选的远端执行节点,只跑 runtime,通过 QUIC 加入集群,实现边缘卸载。
两队列:
- Redis Stream 做事件总线(trigger、webhook、定时器);
- 内嵌的 sled 做本地零依赖队列,保证断网续跑。
整个引擎无全局锁,一条工作流 = 一组有向无环图,每个节点对应一个 WASM 实例;实例生命周期由 server 的「节点池管理器」统一回收,支持秒级弹性缩容到零。
3. 节点热插拔:manifest + host-call 白名单
WASM 节点 = 一个 .wasm + manifest.yaml:
apiVersion: sim.sh/v1
kind: Node
metadata:
name: slack-notify
version: 1.2.0
spec:
entry: slack_notify.wasm
hostCalls: # 必须显式声明,否则调用即报错
- http_post
- secrets_get
memory: 8Mi # 硬上限
timeout: 30s
inputs:
- key: webhook
type: string
required: true
server 收到新 manifest 后:
- 校验签名(minisign);
- 把
.wasm塞进 content-address 存储(blake3 做键); - 向所有 runtime 进程推送「新增节点定义」事件;
- runtime 立即编译并放入「节点模板池」,首次实例化 <50 ms。
更新同理,旧版本实例自然耗尽后自动淘汰,零停机。因为 host-call 列表在编译期就写死,节点想越权调用 docker_run 会直接链接失败,从根子上消灭供应链投毒。
4. 秒级冷启动的编译参数清单
Rust 侧 Cargo.toml 关键段:
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
strip = true
overflow-checks = false
panic = "abort"
[dependencies]
# 禁止任何分配器,全部用 &mut [u8] 手动管理
serde = { version =