wasmtime & wasmer
สองรันไทม์อิสระระดับ production ที่ครองระบบนิเวศ WASI: wasmtime (ดูแลโดย Bytecode Alliance, เขียนด้วย Rust) และ wasmer (เขียนด้วย Rust, ข้ามแพลตฟอร์ม) ทั้งคู่ implement WASI spec, รองรับ ahead-of-time (AOT) compilation และเปิดเผย embedding API สำหรับ Rust, Python, Go และภาษาอื่น ๆ
การติดตั้งรันไทม์
หัวข้อที่มีชื่อว่า “การติดตั้งรันไทม์”# wasmtime — ผ่าน installer scriptcurl https://wasmtime.dev/install.sh -sSf | bash
# wasmer — ผ่าน installer scriptcurl https://get.wasmer.io -sSfL | sh
# ตรวจสอบwasmtime --versionwasmer --versionรัน WASI module ด้วย wasmtime
หัวข้อที่มีชื่อว่า “รัน WASI module ด้วย wasmtime”# รันพื้นฐานwasmtime my_app.wasm
# ส่ง command-line arguments (-- คั่น runtime flag จาก module arg)wasmtime my_app.wasm -- hello world
# ให้สิทธิ์เข้าถึง directorywasmtime --dir /tmp my_app.wasm
# ให้สิทธิ์ด้วย path alias (host path::guest path)wasmtime --dir /host/data::/data my_app.wasm
# ส่ง environment variablewasmtime --env DATABASE_URL=postgres://localhost/db my_app.wasm
# รวม: dir + env + argswasmtime --dir /data --env LOG_LEVEL=info my_app.wasm -- --config /data/cfg.tomlรัน WASI module ด้วย wasmer
หัวข้อที่มีชื่อว่า “รัน WASI module ด้วย wasmer”# รันพื้นฐานwasmer my_app.wasm
# mount directorywasmer --dir /tmp my_app.wasm
# ส่ง environment variablewasmer --env KEY=value my_app.wasm
# รันจาก Wasmer registry (wapm packages)wasmer run python/python -- --versionEmbed wasmtime ในแอปพลิเคชัน Rust
หัวข้อที่มีชื่อว่า “Embed wasmtime ในแอปพลิเคชัน Rust”พลังที่แท้จริงของรันไทม์อิสระคือการ embed — โหลด plugin .wasm ขณะ runtime โดยไม่ต้องคอมไพล์ host application ใหม่
use wasmtime::{Engine, Linker, Module, Store};use wasmtime_wasi::WasiCtxBuilder;
fn run_plugin(wasm_bytes: &[u8]) -> anyhow::Result<()> { let engine = Engine::default(); let module = Module::new(&engine, wasm_bytes)?;
// สร้าง WASI context ขั้นต่ำ — ไม่มี filesystem, ไม่มี env var let wasi = WasiCtxBuilder::new().inherit_stdio().build(); let mut store = Store::new(&engine, wasi);
let mut linker = Linker::new(&engine); wasmtime_wasi::add_to_linker_sync(&mut linker, |s| s)?;
let instance = linker.instantiate(&mut store, &module)?; let start = instance.get_typed_func::<(), ()>(&mut store, "_start")?; start.call(&mut store, ())?; Ok(())}pattern นี้คือวิธีที่ระบบ plugin ทำงาน: host application โหลดไฟล์ .wasm ตามอำเภอใจขณะ runtime และเรียก exported function โดยมี sandbox บังคับ isolation อย่างเข้มงวด
sequenceDiagram
participant Host as Host App (Rust)
participant WT as wasmtime Engine
participant M as Plugin (.wasm)
Host->>WT: Engine::default()
Host->>WT: Module::new(wasm_bytes)
Host->>WT: Linker + WasiCtxBuilder
Host->>WT: linker.instantiate()
WT->>M: instantiate + link imports
Host->>M: typed_func("process").call(args)
M-->>Host: return value ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
WASI capability-based security (--dir/--env) | ปลอดภัยกว่ามาก — module ที่ wasmtime/wasmer รันได้เฉพาะสิทธิ์ที่ flag ระบุไว้อย่างชัดเจน | ยังไม่ compatible กับ POSIX เต็มรูปแบบ binary ที่ port มาจาก native code ซึ่ง assume ambient access จะรันไม่ได้ตรง ๆ |
| Embed wasmtime/wasmer สำหรับ edge/serverless | Cold-start ระดับ microsecond เมื่อเทียบกับการ spin container ใหม่ทุกครั้ง | Container ecosystem ยังมี tooling, orchestration และ library support ที่ mature และกว้างกว่า |
ข้อผิดพลาดที่พบบ่อย
หัวข้อที่มีชื่อว่า “ข้อผิดพลาดที่พบบ่อย”- ลืมส่ง
--dirหรือ--envตอนรัน แล้วแปลกใจว่าทำไม module เข้าถึง filesystem หรือ environment variable ไม่ได้ — ต้อง grant capability ให้ runtime อย่างชัดเจนเสมอ - คิดว่า SIMD หรือ threads proposal รองรับเหมือนกันทุก runtime — wasmtime และ wasmer อาจ support level ต่างกัน ต้อง check ความสามารถของ runtime version ที่ใช้ก่อน deploy
- Embed wasmtime version เก่าเข้ากับ component ที่ build ด้วย Component Model รุ่นใหม่กว่า — WIT interface ที่ยังพัฒนาอยู่ทำให้ binding code เก่าพังตอน link หรือ instantiate
💡 ตัวอย่างจากของจริง
Fermyon Spin build บน wasmtime เพื่อ embed และรัน serverless Wasm module ส่วน Fastly Compute@Edge และ Cloudflare Workers ใช้หลักการ embedding และ sandboxing แบบเดียวกันเพื่อ isolate tenant code ด้วย cold-start ที่ต่ำมาก