だいぶ以前 Plack::Server::AnyEvent::Prefork
というのを書いて某所で使っていたのですが、ここ数日で事例がもうひとつ増えたついでに Twiggy ベースに書き直してCPANリリースしました。
https://metacpan.org/module/Twiggy::Prefork
使うには、
$ plackup -s Twiggy::Prefork -a app.psgi
な感じで、Server::Starterにも対応しているので、
$ start_server --port 5000 -- plackup -s Twiggy::Prefork -a app.psgi
とすれば、hot-deployも可能です。
起動オプションは、Twiggyがサポートしているオプションに加えて、
- —max-workers preforkするworker数
- —max-reqs-per-child 1プロセスあたりのリクエスト数
- —min-reqs-per-child 1プロセスあたりの最小リクエスト数。maxとminとの間でランダムな数字になる
の3つが追加されています。
あと、psgix.exit_guardというリクエストの環境変数からサーバ内部の Condition Variables
にアクセスができるようにしてあります。これを使うと 優雅にgraceful shutdownが実現できます。
以下はその例。max-reqs-per-childに達したあと、すぐにプロセスが終了せずに、1個目のasync内のジョブがすべて解消されるまでは待ちます。
use Coro;
use AnyEvent;
my $channel = Coro::Channel->new(100);
async {
while(1){
my $q = $channel->get;
# works..
$q[0]->end;
}
};
#psgi app
sub {
my $env = shift;
my $cv = AE::cv;
async {
$env->{psgix.exit_guard}->begin;
$channel->put([$env->{psgix.exit_guard}]);
$cv->send;
};
return sun {
my $start_response = shift;
$cv->cb(sub {
$start_response->([200,['Content-Type'=>'text/plain'],['OK']]);
});
}
}
Plack::Server::AnyEvent::Preforkはすでに動作実績があり、そのコードをベースにしているので比較的安心して使えると思います。どうぞお試しください。