Onyx言語でHTTPサーバーを実装し、Wasmer Edgeにデプロイする
こんにちは、ナカエです。 先週末は少し暖かかったかと思えばまた寒くなりましたね。
本日の記事はWasmer Edgeというエッジにアプリケーションをデプロイできるサービスと新しいプログラミング言語である Onyx を合わせて試したという内容です。
まずはそれぞれの簡単な紹介から入ります。
Wasmer Edgeとは
Wasmer Edge はエッジロケーションにWebAssemblyのランタイムを展開し、Wasmバイナリをアプリケーションとして安価にスケーラブルに動かせると謳うサービスです。米Wasmer社が提供しています。
個人的にはブラウザ側だけでなくサーバー側であるエッジでまでJavaScript/TypeScriptという選択肢だけになるのはちょっと……という気持ちがあり、エッジでのWasmの実行についても興味を寄せています。
ユーザーに近いロケーションでコンテナを動かす、ということであれば Fly.io などでもやっていることですが、Wasmランタイムがコンテナランタイムの代替手段となりえるならセキュリティ面やパフォーマンス面で有利です。利用側もアプリの実装以外で考えることが減るのではないかと期待しています。
Docker DesktopにWebAssemblyランタイムが統合される などの動きもあり、今後エコシステムの整備は加速していきそうです。
Wasmer Edge はまだBetaではありますが10/6にGAとなっており、Tokyoリージョンも追加されています。
競合との比較にてコールドスタートが 50ナノ秒と表記されていたり、HTTP接続だけではなくTCP接続も扱えるとメリットをアピールしており、自信のほどが窺えます。
言語サポートには Rust, JS, C, Python, Ruby
とあり、現時点でも一般的なエッジコンピューティングのサービスより対応幅が広いです。Wasmを生成できるなら言語はなんでもいい、という感じになってくれれば素晴らしいですね。
プログラミング言語 Onyx とは
Wasmer社がブログで紹介したことで話題になった Onyx はWebAssemblyへのコンパイルに特化した言語で、開発者は Brendan Hansen 氏です。
Wasm特化というだけあってWebAssemblyへのコンパイルが非常に高速とのこと。
また、Onyxの構文は、Go、Jai、Odinといった他の命令型プログラミング言語にインスパイアされているそうですが、パイプ演算子など関数型プログラミングのスタイルに合う言語機能も用意されています。
さて、ここからはOnyxとWasmer Edgeを試してみましょう。
環境
- macOS Monterey
- Intel Core i5
- Wasmer CLI 4.2.4
- Onyx v0.1.8
- zsh 5.8.1
今回はWasmerへのアカウント登録手順は割愛し、すでにアカウントを保持しているものとします。
Onyxのインストール
Onyxの公式サイト の説明に従い、下記のワンライナーを実行します。
sh <(curl https://get.onyxlang.io -sSfL)
インストール後はターミナルを新規に開き、 onyx version
コマンドにて、バージョンとランタイムを確認できます。
$ onyx version
Onyx toolchain version v0.1.8
Built on Wed Nov 29 01:49:11 2023
Runtime: wasmer
Onyxのパッケージの作成
以下はドキュメントの HTTP Server in Onyx を参考に進めます。
まずはディレクトリを作ってOnyxのパッケージを作成し、
mkdir my-http-server
cd my-http-server
onyx package init
今回利用する http-server
のパッケージを依存として追加します。
onyx package add http-server
onyx package sync
パッケージの設定は onyx-pkg.kdl
というファイルに保存されているようですね。
$ cat onyx-pkg.kdl
package {
name "my-http-server"
author "n1215"
url ""
description "My first HTTP Server project"
version "0.0.1"
}
config {
dependency_source_path "./lib"
dependency_binary_path "./bin"
}
dependencies {
http-server "0.2.24" git="http://github.com/onyx-lang/pkg-http-server"
}
HTTPサーバーの実装
サーバーが返すHTMLを少し変更していますが、おおむねドキュメントの通りです。
#load "./lib/packages"
use core {*}
use http
use http.server { Request, Response, route }
#tag route.{ .GET, "/" }
index :: (req: &Request, res: &Response) {
res->html("<h1>Http Server in Onyx!</h1>");
res->status(200);
res->end();
}
main :: () {
router := http.server.router();
router->collect_routes();
http.server.cgi(&router);
}
Wasmerにデプロイする前提で、http.server.tcp
ではなく、http.server.cgi
を利用しているところがポイントです。
Wasmバイナリを生成
コードをコンパイルして、WASIランタイム向けのWasmを生成します。
onyx build main.onyx -r wasi -o my-http-server.wasm
ちなみに生成したWasmのファイルサイズは250KBでした。
さて、記事の後半ではこのWasmをWasmerにデプロイしていきます。
WasmerのCLIをインストール
Wasmerにデプロイするアプリケーションの操作は公式のCLIを通じて行います。
Install Wasmer に従って
curl https://get.wasmer.io -sSfL | sh
を実行するだけでOKです。
wasmer --version
コマンドにて、Wasmerがインストールされていることを確認できます。
$ wasmer --version
wasmer 4.2.4
Wasmer アプリケーションの作成
wasmer.tomlの作成
デプロイの前にWasmer側にアプリケーションを作成する必要があります。
下記の内容でwasmer.tomlファイルを作成します。 <your-namespace>
と <your-package-name>
は適宜置き換えてください。
[package]
name = "<your-namespace>/<your-package-name>"
version = "0.1.0"
description = "My first HTTP server"
license = "MIT"
[[module]]
name = "server"
source = "my-http-server.wasm"
abi = "wasi"
[[command]]
name = "server"
module = "server"
runner = "https://webc.org/runner/wcgi"
[command.annotations.wasi]
env = ["SCRIPT_NAME=rust_wcgi"]
[command.annotations.wcgi]
dialect = "rfc-3875"
次に
wasmer login
で登録したアカウントでログインし、
wasmer app create
のコマンドを実行してHTTP serverを選択します
$ wasmer app create
App type:
Static website
> HTTP server
Browser shell
JS Worker (experimental)
Python Application
ほかにも設定がありますが、wasmer.tomlに設定されている内容が利用されるので基本的にはデフォルトを選択で大丈夫です。
wasmer deploy
コマンドを試したいので、最後の質問の「Would you like to publish the app now?」のみnoを選択しておきます。
$ wasmer app create
App type: HTTP server
Who should own this package?: n1215
Found local package: 'n1215/my-http-server@0.1.0'
Use package 'n1215/my-http-server' yes
What should be the name of the app? <NAME>.wasmer.app: n1215-my-http-server
Would you like to publish the app now? no
Writing app config to '/Users/ken/Workspace/my-http-server/app.yaml'
To (re)deploy your app, run 'wasmer deploy'
この時点でapp.yamlが生成されているのが確認できます
---
kind: wasmer.io/App.v0
name: n1215-my-http-server
package: n1215/my-http-server
debug: false
Wasmer へのデプロイ
デプロイは下記コマンドを実行するだけです。
wasmer deploy
アプリの公開URLは wasmer app create
コマンドで指定したものとなっています。 バージョンごとにも https://{英数}.id.wasmer.app
のようなURLが発行されるようです。
アクセスすると、HTTPサーバーの動作が確認できます。
まとめ
WebAssemblyに特化したプログラミング言語Onyxを利用してWasmバイナリを作成してWasmerにデプロイし、動作を確認できました。
Onyx言語はツールチェインを含めなかなか使いやすそうです。 WasmerはHerokuやFly.ioのようにCLIだけでサクッとデプロイできるのも手軽で良いですね。 エッジでのWasmの実行については、今後も動向を注視していこうと思います。
- WebAssembly , エッジコンピューティング , Onyx , Wasmer