In acest weekend am incercat sa pornesc aplicatii cu conexiuni de internet (tcp) scrise in rust si compilate pentru formatul wasm.
Programele compilate in format wasm se pot executa cu wasmer (cel mai rapid, dar fara tcp) sau cu wasmtime (rapid si promite tcp) sau cu wasmedge (de 20 de ori mai lent decat wasmer si wasmtime, dar are un exemplu functional de server tcp) sau cu multe altele netestate de mine.
Programele wasm se executa in mediu izolat (ca un container docker) si nu au acces direct la sistemul de fisiere si la reteaua internet, e nevoie de configurare explicita a drepturilor. Avantajul wasm este ca nu necesita suport de virtualizare din partea procesorului (docker cere asta). Wasm este un format executabil menit sa functioneze intr-un interpretor de masina virtuala cu posibilitatea de compilare nativa a codului in timpul executiei.
Toate testele cu acces la foldere si fisiere au mers perfect cu wasmer, wasmtime si wasmedge, dar suportul de conexiuni internet/tcp/udp nu.
Desi in documentatie wasmtime promite (cu comanda wasmtime run --tcplisten localhost:9000 fisier.wasm) suport tcp, nu am reusit sa compilez cu succes o solutie functionala in Rust. Am gasit exemple pentru dot net si ce exemple am gasit pentru Rust au functionat partial, iar documentatia Rust nu prea ofera exemple potrivite penttu copy/paste (spre deosebire de Python, care o face foarte bine) si standardul wasi privind conectivitatea tcp inca nu este definitivat.
wasmer inca nu suporta conexiuni tcp, iar wasmedge merge perfect cu Rust, dar este foarte lent.
Un film care compara performantele wasmer si wasmtime fata de executia nativa: https://www.youtube.com/watch?v=QlMLB2-G25c
Dar astazi, luni, am observat ca spin (o solutie de care am auzit cu cateva saptamani in urma, film1 si film2) rezolva toate problemele de conectivitate tcp folosind un runtime de wasm propriu si rapid (la fel de rapid ca wasmer sau wasmtime) si cu minim de cod si ceva configuratie atent construita:
spin_version = "1"
authors = ["ioan"]
description = ""
name = "my-test"
trigger = { type = "http", base = "/" }
version = "0.1.0"
#
# Toate componentele sunt aici
#
[[component]]
id = "index"
source = "index/target/wasm32-wasi/release/index.wasm"
# asta da voie codului din container sa acceseze internetul
allowed_http_hosts = ["insecure:allow-all", "https://some-random-api.ml", "https://postman-echo.com"]
environment = { DB_URL = "host=localhost user=postgres dbname=spin_dev", A = "1", B = "2" }
[component.trigger]
route = "/..."
[component.build]
command = "cd index && cargo build --target wasm32-wasi --release"
[[component]]
id = "m1"
source = "m1/target/wasm32-wasi/release/m1.wasm"
[component.trigger]
route = "/m1"
[component.build]
command = "cd m1 && cargo build --target wasm32-wasi --release"
[[component]]
id = "m2"
source = "m2/target/wasm32-wasi/release/m2.wasm"
[component.trigger]
route = "/m2"
[component.build]
command = "cd m2 && cargo build --target wasm32-wasi --release"
Ca sa pornesc in Linux aplicatia spin formata din trei module (index, m1 si m2) si scrisa in Rust:
spin build
if [ $? -ne 0 ]; then
echo
echo "Eroare compilare"
echo
else
spin up --listen 0.0.0.0:5000
fi
Sau in windows (in masina virtuala VirtualBox cu drive z: mapat catre zona de lucru din Linux):
@echo off
z:
cd Z:\MyData\Research\Rust\teste\wasm\spin\test2-app-complexa
c:\1\spin\spin up --listen 0.0.0.0:5000
pause
Eu dezvolt aplicatii pe calculator cu Linux, dar toate programele testate (wasmer, wasmtime, wasmedge si spin) au varianta de program si pentru Windows si aplicatiile compilate in format wasm sunt incarcate si executate fara probleme in orice sistem de operare suportat: Windows, Linux, Android, Darwin, …