私Mojolicious::Lite
は、websocket エンドポイントを含む単純なベースのサーバーで作業しています。
Websocket 接続を正常に終了し、クライアント (Java アプリケーション) での例外を回避するために、いくつかの終了シグナルを処理したいと考えています。
を使用して以前のサーバーで慣れていたように、シグナルハンドラーを定義しようとしましたHTTP::Daemon
。問題は、それらが無視されているように見えることです。モジョリシャス層で再定義されたのかもしれませんが、まだ参考文献は見つかりませんでした。
終了メッセージが表示されることを期待していますが、表示されません
[Mon Mar 23 14:01:28 2020] [info] Listening at "http://*:3000"
Server available at http://127.0.0.1:3000
^C # <-- i want to see my signal received message here if type Ctrl-c
SIGINT
サーバーが端末でフォアグラウンドにあるときに入力して直接送信しCtrl-C
ています。サーバーを正常に終了できます(たとえば、cronまたはその他の表示のない手段によって開始された場合)kill <pid>
.
以前のいくつかのサーバーでは、以下を処理することで非常に徹底的にしようとしました:
HUP
設定をリロードするために現在使用されているハイジャックされたシグナルSIGINT
Ctrl+CSIGQUIT
Ctrl-\SIGABRT
例: ライブラリの異常終了SIGTERM
外部終了要求 - 「友好的」kill
(残忍な反対による)kill -9
TSTP
Ctrl-Z でサスペンドCONT
または を使用して Ctrl-Z から再開するfg
場合bg
これらのハンドラーはすべて、プログラムとニーズに応じて、リソースをクリーニングして正常に終了し、データの一貫性を確保したり、外部変更後に構成またはデータ モデルをリロードしたりできます。
Mojo::IOLoop::Signal
«ノンブロッキングシグナルハンドラー»というパッケージを見つけましたが、それは別のもののようです。違う?
これが私の簡略化されたコードです(単純な で実行されますperl ws_store_test.pl daemon
):
ファイル ws_store_test.pl
# Automatically enables "strict", "warnings", "utf8" and Perl 5.10 features
use Mojolicious::Lite;
my $store = {};
my $ws_clients = {};
sub terminate_clients {
for my $peer (keys %$ws_clients){
$ws_clients->{$peer}->finish;
}
}
$SIG{INT} = sub {
say "SIGINT"; # to be sure to display something
app->log->info("SIGINT / CTRL-C received. Leaving...");
terminate_clients;
};
$SIG{TERM} = sub {
say "SIGTERM"; # to be sure to display something
app->log->info("SIGTERM - External termination request. Leaving...");
terminate_clients;
};
# this simulates a change on datamodel and notifies the clients
sub update_store {
my $t = localtime time;
$store->{last_time} = $t;
for my $peer (keys %$ws_clients){
app->log->debug(sprintf 'notify %s', $peer);
$ws_clients->{$peer}->send({ json => $store
});
}
}
# Route with placeholder - to test datamodel contents
get '/:foo' => sub {
my $c = shift;
my $foo = $c->param('foo');
$store->{$foo}++;
$c->render(text => "Hello from $foo." . (scalar keys %$store ? " already received " . join ', ', sort keys %$store : "") );
};
# websocket service with optional parameter
websocket '/ws/tickets/*id' => { id => undef } => sub {
my $ws = shift;
my $id = $ws->param('id');
my $peer = sprintf '%s', $ws->tx;
app->log->debug(sprintf 'Client connected: %s, id=%s', $peer, $id);
$ws_clients->{$peer} = $ws->tx;
$store->{$id} = {};
$ws->on( message => sub {
my ($c, $message) = @_;
app->log->debug(sprintf 'WS received %s from a client', $message);
});
$ws->on( finish => sub {
my ($c, $code, $reason) = @_;
app->log->debug(sprintf 'WS client disconnected: %s - %d - %s', $peer, $code, $reason);
delete $ws_clients->{$peer};
});
};
plugin Cron => ( '* * * * *' => \&update_store );
# Start the Mojolicious command system
app->start;