Viceroyを眺める
便利そうなプレスリリースが出て、色々調べてたら開発用ローカルサーバーのコードが見つかったので土曜の夜の暇つぶしに眺めてみる。
開発用ローカルサーバーのコードを読んだところでなんだという感じなのだが....
登場人物
概念
- downstream request/response: クライアントから飛んできたリクエスト/レスポンス
- upstream request/response: バックエンド系に飛んでいくリクエスト/レスポンス
ゲスト側
fastly
create
Fastly Compute@EdgeのSDK。リポジトリは非公開のようだがcrate.ioやdocs.rsでホストされており、コード自体は見れる。
fastly-sys
上述のfastly
createが呼び出すFFIをextern "C"
で定義.
要はユーザーの書いたwasmモジュールにimportされる関数のシグニチャを定義しているにすぎない。基本なんでもハンドルを経由して動かす。
ホスト側(Viceroy)
MozillaからFastlyに移籍したWasm/Rust組がIssueとかでよく見かける(当たり前)。
Viceroy (rev. 28e4078e時点)
fastly CLIでfastly compute serve
すると起動する「開発用ローカルサーバー」の実態。
今のところ未実装なものが色々あるが、読んで遊ぶには十分。
Fastly社の各種発表を聞くに、商用環境のホスト側はlucetでwasmモジュールAOTコンパイルした上で実行しているらしい。一方、こちらはwasmtimeを使っているのでサーバー起動時にwasmtime::Module
を生成、各リスエストごとに実行時に環境(後述のSession
とリンクしてwasmtime::Instance
を作って実行する。
アプリケーション自体はhyper
を使って書かれているのでいろいろasync/awaitする.
compute-at-edge-abi
witx(初めて知った)で記述されたABI定義。fastly-sys
に対応する定義が記載されている。
Viceroyではwiggle
の提供するprocedural macroを用いて、viceroy_lib::wiggle_abi
との対応を取る
viceroy_lib::session::viceroy_lib
downstream requestごとに生成される.
上述のcompute-at-edge-abi
で定義されたABIもほぼこの上に実装されている.
処理の流れ
作るのがめんどくさいのでシーケンス図は省略
一番美味しいところはExecuteCtx::run_guest()
を読めばよい.
各downstream requestに対するゲストコード(wasmコード)は、tokio::task::spawn()
される。デスヨネー。
各Session
はtokioのchannelのSender
を持っているので、downstream responseが打ち返されたら(fastly_sys::fastly_http_resp::send_downstream
が呼び出されたら)、渡ってきたSender
に詰める.
つまり、ゲストコードがfastly::Response::send_to_client
( fastly::ResponseHandle::stream_to_client
)やfastly::Response::stream_to_client
(fastly::ResponseHandle::stream_to_client
)を(ユーザーまたは#[fastly::main]
によって生成されたコードが)呼び出すことで、処理がホスト側に渡る。
もちろんホスト側ではそれを待ち構えているので、うまいことハンドルして終わり。
感想
小さいしRustで書かれてるので読みやすい。Proxy-Wasmな、Wasmな任意コードを動かす配信サーバーの実装例 + ユーザー向けSDKの作り方としても読める感じだった。
ただFastlyというCDNサービスを使う側の視点としてViceroyを見た場合、あくまでもFastly Compute@Edgeのユーザー用ローカル開発シミュレータ専用に実装されたようにも読めるので、本番との挙動の差異をどうやって埋めていくかが気になるところ。テストスイートとかどうするんだろう?