TL;DR

Fermyon 社が開発している OSS のマイクロサービスフレームワーク。wasi:http/[email protected] を実装した WebAssembly Component としてサービスをビルドし、動かす。

なぜ必要か

サービスをイベント駆動型で記述できる。wasi:http/[email protected] を実装した WebAssembly Component をビルドでき、そうした Component をアプリの一部として動かすこともできる。Docker や Kubernetes 上での実行にも対応している。

仕組み

Spin CLI

プロジェクトの作成やビルド、起動は CLI で行う。CLI は Homebrew でインストールできる。

$ brew tap fermyon/tap
$ brew install fermyon/tap/spin
$ spin -h

spin new <名前> でプロジェクトを作る。実行すると、http-rust や http-go、http-empty などのテンプレートから選ぶよう聞かれる。http-empty を選ぶと、マニフェストファイル spin.toml だけが作られる。

spin.toml

spin.toml は Spin プロジェクトのマニフェストファイルで、アプリで使う WebAssembly Component とトリガを設定する。Component は [component.<アプリ内で使う名前>] テーブルに書き、source に WASM ファイルへのパスを指定する。Web で公開されている Component なら、URL とダイジェストを指定してもよい。

[component.hello-world]
source = "./hello_wasi_http.wasm"

トリガ

トリガは、設定したパターンにマッチするパスへアクセスがあったときに、対応する Component を呼び出す機能である。一般的な Web フレームワークのルーティングにあたる。[[trigger.http]] に、component(spin.toml で定義した Component 名)と route(呼び出すパス)を書く。

[[trigger.http]]
component = "hello-world"
route = "/hello-world/..."

spin up でアプリケーションを起動する。デフォルトでは 3000 番ポートで待ち受ける。

Component の追加とビルド

spin add を使うと、Spin が提供する高水準な API で Component を開発できる。テンプレートと呼び出すパスを聞かれ、Rust なら Cargo.toml と src/lib.rs を持つディレクトリが作られる。同時に spin.toml にも Component とビルドの設定が追加される。

use spin_sdk::http::{IntoResponse, Request, Response};
use spin_sdk::http_component;
 
#[http_component]
fn handle_echo(req: Request) -> anyhow::Result<impl IntoResponse> {
    Ok(Response::builder()
        .status(200)
        .header("content-type", "text/plain")
        .body("Hello, Fermyon")
        .build())
}

#[http_component] マクロは、直後の関数を handler 関数の実装にする。handler 関数は、wasi:http/proxy World の wasi:http/incoming-handler インタフェースを実装する関数である(第7章 Hello, wasi:http/proxy)。これにより、ビルドした Component は wasi:http/proxy World を実装する。incoming-request などのリソースは、Spin が提供するラッパを通じて操作する。

受信した HTTP リクエストは Request として渡され、body メソッドでボディを取り出せる。レスポンスは Response::builder で作った ResponseBuilder に、status、header、body を設定し、build で組み立てる。

spin build でビルドする。wasm-tools で成果物の World を見ると、wasi:http/proxy が import するインタフェースに加えて、fermyon:spin/key-value などの Spin 固有のインタフェースにも依存していることが分かる。

注意点

spin add で生成される設定は、デフォルトのビルドターゲットが wasm32-wasi になっている。wasm32-wasip1 を使う場合は、spin.toml の source と command を書き換える。

関連

出典