Runtimes Host WASI: wasmtime, wazero y Spin
Un binario wasip1/wasm es solo la mitad de la historia.
Busca en todas las páginas de la documentación
Un binario wasip1/wasm es solo la mitad de la historia.
Algo debe instanciar el módulo, satisfacer las importaciones WASI y, opcionalmente, mapear disparadores HTTP o capacidades del sistema de archivos.
wasmtime, wazero y Spin son los tres hosts que los equipos de Go eligen primero: herramientas CLI, incrustación en procesos y HTTP en el edge, respectivamente.
Compila Go con GOOS=wasip1 GOARCH=wasm, luego ejecuta el artefacto a través de un host que hable WASI Preview 1.
wasmtime sobresale en el desarrollo local y scripting.
wazero encaja en microservicios Go que cargan plugins en el proceso.
Spin empaqueta manejadores HTTP con opinión para despliegues en el edge al estilo Fermyon.
Cada host difiere en cómo otorga capacidades de sistema de archivos, entorno y red.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
# Bucle de desarrollo
GOOS=wasip1 GOARCH=wasm go build -o app.wasm .
wasmtime run --env APP_ENV=dev --dir .::/work app.wasm// Incrustar con wazero (host Go)
wasi_snapshot_preview1.MustInstantiate(ctx, runtime)
mod, _ := runtime.Instantiate(ctx, wasmBytes)
_, _ = mod.ExportedFunction("_start").Call(ctx)Cuándo usar esto:
Invitado (guest/main.go):
package main
import (
"fmt"
"os"
)
func main() {
name, _ := os.Hostname()
fmt.Println("hostname:", name)
fmt.Println("env:", os.Getenv("GREETING"))
}Compilar:
GOOS=wasip1 GOARCH=wasm go build -o guest.wasm ./guestwasmtime:
wasmtime run --env GREETING=hello --dir .::/ guest.wasmHost wazero (host/main.go):
package main
import (
"context"
"os"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
)
func main() {
ctx := context.Background()
r := wazero.NewRuntime(ctx)
defer r.Close(ctx)
wasi_snapshot_preview1.MustInstantiate(ctx, r)
cfg := wazero.NewModuleConfig().
WithEnv("GREETING", "hello from wazero").
WithFSConfig(wazero.NewFSConfig().WithDirMount(".", "/"))
wasm, _ := os.ReadFile("guest.wasm")
mod, _ := r.InstantiateWithConfig(ctx, wasm, cfg)
defer mod.Close(ctx)
_, _ = mod.ExportedFunction("_start").Call(ctx)
}Spin (spin.toml extracto + build):
spin_manifest_version = 2
[application]
name = "go-guest"
version = "0.1.0"
[[trigger.http]]
route = "/..."
component = "guest"
[component.guest]
source = "guest.wasm"
[component.guest.trigger]
route = "/"spin build
spin upLo que esto demuestra:
_start (o los wrappers main exportados) se ejecuta después de la instanciación.| Runtime | Lenguaje | cgo | Uso Típico | Historia HTTP |
|---|---|---|---|---|
| wasmtime | Núcleo Rust, enlaces multi-lenguaje | Opcional en enlaces | CLI, plataformas políglotas | A través de propuestas WASI HTTP / incrustar personalizado |
| wazero | Go Puro | No | Servicios Go incrustando plugins | Montas net/http alrededor de las llamadas al invitado |
| Spin | Runtime Rust + lenguajes invitados Go/otros | No para invitados Go | Microservicios en el edge | Disparadores HTTP de primera clase |
Call limitan el tiempo de CPU; combínalo con APIs de medición de combustible cuando estén disponibles.// ABI de plugin estrecha: el invitado lee JSON de stdin, escribe JSON de stdout.
// El host envuelve Call con buffers a través de las anulaciones de stdin/stdout de ModuleConfig.Falta la instanciación WASI en wazero - Olvidar wasi_snapshot_preview1.MustInstantiate produce errores de importación oscuros. Solución: siempre registra WASI antes que los módulos invitados.
Asumiendo el directorio de trabajo - Los invitados solo ven rutas pre-abiertas, no el CWD del host. Solución: monta . explícitamente en / o /work.
Expectativas de red de Spin - No todos los servidores Go net/http compilan a un componente Spin sin adaptación. Solución: sigue los patrones del SDK de Spin para Go para los manejadores HTTP.
Desajuste de versión de wasmtime - Los hosts más antiguos carecen de instantáneas WASI más nuevas. Solución: fija wasmtime en CI para que coincida con la producción.
Re-instanciar por solicitud sin caché - La compilación domina la latencia en frío. Solución: almacena en caché los módulos compilados; reutiliza wazero.CompiledModule.
Pasar rutas de host sensibles - --dir /::/ demasiado amplio rompe el sandboxing. Solución: monta directorios de mínimo privilegio por invitado.
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| Wasmer | Ya te estandarizas en él | El equipo quiere un incrustador puramente Go (wazero) |
| Node + WASI experimental | Tienda JS, scripts pequeños | Incrustación de Go en producción |
Plugins nativos (.so) | Máximo rendimiento, código confiable | Código de inquilino no confiable |
| MicroVMs Firecracker | Aislamiento fuerte más allá de WASM | Se requieren arranques en frío de sub-milisegundo |
wazero es Go puro: binarios estáticos más simples, sin cgo, propagación natural de context.
wasmtime sigue siendo excelente para CLI/desarrollo y hosts políglotas.
Sí. Instancia múltiples módulos en un runtime, o aísla runtimes por inquilino para separación de memoria.
No. Spin ejecuta módulos wasip1 compilados con gc, pero los límites de tamaño pueden empujarte hacia TinyGo o -ldflags=-s -w.
fmt.Println a stdout/stderr se mapea a los logs del host.
Captura en wazero a través de los escritores stdout de ModuleConfig.
Sí, a través de importaciones personalizadas en wazero (DefineModuleBuilder) o APIs de enlazador de wasmtime.
Mantén la ABI estrecha y versionada.
Verifica el soporte de sockets WASI de cada runtime.
Spin expone HTTP en la capa de disparador en lugar de sockets crudos para muchas aplicaciones.
Trata .wasm como artefactos inmutables versionados en almacenamiento de objetos.
Intercambia bytes del módulo y reinstancia; Spin lo maneja a través de spin deploy.
wazero soporta tiempos de espera de ejecución a través del contexto; la medición avanzada evoluciona por versión; verifica la documentación para tu versión fijada.
Sí si las importaciones WASI coinciden.
Prueba ambos en CI cuando incrustes en Go pero desarrolles con la CLI de wasmtime.
Usa rutas mapeadas por WASI con montajes de solo lectura para entradas y montajes escribibles solo donde se requiera persistencia.
Versiones de Stack: Esta página fue escrita para Go 1.26.x (predeterminado Green Tea GC, modernizadores de
go fix- verifica el parche en la compilación), chi (última - verifica en la compilación), gin (última - verifica en la compilación), echo (última - verifica en la compilación), google.golang.org/grpc (última - verifica en la compilación), sigs.k8s.io/controller-runtime (última - verifica en la compilación), kubebuilder (última - verifica en la compilación), tinygo (última - verifica los objetivos de placa en la compilación), wazero (última - verifica en la compilación), y golangci-lint (última - verifica el conjunto de linters en la compilación).
Revisado por Chris St. John·Última actualización: 16 jul 2026