Server::Starter を Haskell で利用するためのライブラリを書きました。 warp で動かすWEBアプリでも、 start_server
コマンドを使った hot-deploy が可能になります。とりあえず github にのみ上げました。
以下でサンプルプログラムまで含めてビルドできます。
$ git clone git@github.com:hiratara/hs-server-starter.git
$ cd hs-server-starter/
$ stack build --flag hs-server-starter:example
使い方
https://github.com/hiratara/hs-server-starter/blob/master/app/server-starter-warp-example.hs を見てください。
Network.ServerStarter.Socket
を import
して、 listenAll
を呼び出すと listen
状態の Socket
が返ってきます。この Socket
は Server::Starter
の管理下にある接続であり、これを利用することでホットデプロイが可能になります。 warp
で使うのであれば、 runSettingsSocket
関数に渡すことでこの Socket
に対して accept
させられます。
使用例: PerlのWebアプリをHaskellのWebアプリに無停止で差し替える
普通はWebアプリの新しい版をアップロードして、無停止で新しい版に差し替えれるよってことをやるのですが、今回はあえて変な例でやってみます。 start_server
はここでは Perl
で実装されたオリジナルのものを利用するものとします。
Server::Starter
は Perl と cpanm
コマンドの環境を整えた上で cpanm Server::Starter
で導入できます。また今回の例の中で使うため、 cpanm Starlet
でついでに Perl のWEBアプリケーションサーバである Starlet も導入しておきます。
app.sh
を以下の内容で作ります。このシェルは Starlet
で動く簡単なアプリを立ち上げるものです。
#!/bin/sh
exec plackup -s Starlet -e 'sub { [200, [], ["Hello, perl.\n"]] }'
start_server
を使ってこのアプリを起動します。
$ start_server --port 12345 -- ./app.sh
start_server (pid:29812) starting now...
starting new worker 29827
...
http://localhost:12345 へアクセスすると、ページが見えるはずです。
$ curl http://localhost:12345
Hello, perl.
Server::Starter
を使うと、システムを停止することなくオンラインのままこのアプリを warp
で動く Haskell の実装に差し替えることができます。 app.sh
を以下のように編集します。
#!/bin/sh
exec stack exec server-starter-warp-example
ここではまだ、 http://localhost:12345 は Starlet
で動くPerlのアプリがレスポンスを返しています。ここで、サーバを差し替えるために start_server
のプロセスに -HUP
シグナルを送ります。PIDは start_server
の起動直後のログでわかります。
$ kill -HUP 29812
もう一回 http://localhost:12345 へアクセスしてみると、サーバが切り替わっていることがわかります。
$ curl http://localhost:12345
Hello, Web!
簡単ですね!
ただし、Haskellではファイルディスクリプタを O_NONBLOCK
にする必要があるため、今回のようにブロッキングなファイルディスクリプタと共用させるとトラブルの元ですので十分注意が必要です1。
golang実装
start_server
コマンドには golang の実装 もあり、 go get github.com/lestrrat/go-server-starter/cmd/start_server
でインストールできます。当然 golang 版の start_server
コマンドを使っても同じことができます。
Perl版とgolang版はコマンド名が完全に同じであるため、両方インストールして挙動を見るときはどちらの実装を使っているか気をつけて検証してください。
-
ブロックしない
accept
で待つのでPerl側のWebアプリがCPU使い潰したり。深追いしてないけどgolang版だと問題起きなそうだった。 ↩