最近、弊社でもいくつかのサービスでStarmanが動き始めてます。リソース監視厨としてStarmanStarletといったPreforkなPlackサーバにおいてもApacheのmod_status同様、使用されているプロセス数、アイドル中のプロセス数を当然知りたいわけです。CloudForecastでグラフにしたいわけです。

すでにcho45氏がその機能を実現しています。cho45++です。ただ、ステータス表示を行うMiddlewareの他にステータス情報の変更を行うためにStarmanやStarletの本体に手を入れており、若干使いにくいという印象を持っていました。そこでMiddlewareだけで、Middlewareのできる範囲でステータスを変更・表示するPlack::Middleware::ServerStatus::Liteを書いてみました。ソースコードはgithubにpushしてあります。

http://github.com/kazeburo/Plack-Middleware-ServerStatus-Lite

仕組みは簡単です。cho45氏の実装をまねて $0 ($PROGRAM_NAME)を変更し、それをpsコマンド経由で収集し、表示します。

$0を変更する実装は以下の様な感じ

sub call {
    my ($self, $env) = @_;

    $0 = sprintf("server-status-lite[%s] %s",getppid, "A"); #Active

    $res = $self->app->($env);

    $0 = sprintf("server-status-lite[%s] %s",getppid, "_"); #Idle

    return $res;
}

このようにappを実行する前後でステータスをActive(Busy) or Idleで変更しているだけです。Apacheのmod_statusやcho45氏のhackではリクエストの読み込み、書き込み、KeepAliveなどの様々なステータスがとれるのに対してServerStatus::Liteでは2種類の状態しかとることができません。ただ、実際のStarmanやStarletのProduction環境では、リバースプロキシーを全面に設置するため読み込み、買い込みは十分に早くでき、またKeepAliveは無効にしていると思われるので、この簡単なステータスでも十分に焼くに立つのではないかと予想しています。

このように書き換えたステータスをpsコマンドの結果から収集して、Active(Busy)のプロセス数、Idleのプロセス数を数えます。必要なプロセスをすべて調査するために「親プロセスのPIDが同じ」であるプロセスを探しています。

以下は実際にStarlet(max-process=10)でアプリケーションを起動してabでアクセスしている状態のpsの結果(一部)

 PPID   PID COMMAND
20337  1022  \_ /bin/zsh
 1022 20582  |   \_ /usr/bin/perl /usr/local/bin/plackup -r -Ilib -p 5003 -s Starlet -a nonopaste.psgi
20582 20583  |       \_ /usr/bin/perl /usr/local/bin/plackup -r -Ilib -p 5003 -s Starlet -a nonopaste.psgi
20583 20803  |           \_ server-status-lite[20583] _ 127.0.0.1 localhost:5003 GET / HTTP/1.0
20583 20804  |           \_ server-status-lite[20583] A 127.0.0.1 localhost:5003 GET / HTTP/1.0
20583 20806  |           \_ server-status-lite[20583] _ 127.0.0.1 localhost:5003 GET / HTTP/1.0
20583 20808  |           \_ server-status-lite[20583] _ 127.0.0.1 localhost:5003 GET / HTTP/1.0
20583 21153  |           \_ server-status-lite[20583] _ 127.0.0.1 localhost:5003 GET / HTTP/1.0
20583 21156  |           \_ server-status-lite[20583] _ 127.0.0.1 localhost:5003 GET / HTTP/1.0
20583 21158  |           \_ server-status-lite[20583] _ 127.0.0.1 localhost:5003 GET / HTTP/1.0
20583 21163  |           \_ server-status-lite[20583] _ 127.0.0.1 localhost:5003 GET / HTTP/1.0
20583 21165  |           \_ server-status-lite[20583] A 127.0.0.1 localhost:5003 GET / HTTP/1.0
20583 21168  |           \_ /usr/bin/perl /usr/local/bin/plackup -r -Ilib -p 5003 -s Starlet -a nonopaste.psgi

最も左側の項目が親プロセスのPIDで、ここが20583になっているプロセスがPreforkされているプロセスです。6行目と13行目のプロセスが動いているプロセス。一番下のプロセスはまだ一度もアクセスを処理していないので、元のプログラム名のままとなっています。このようなプロセスはIdleのプロセスとカウントしています

このステータス情報はApacheのmod_status同様http経由で取得可能です。おしゃれなHTMLに整形されていたりしませんが以下のように取得可能です

 % curl -v http://localhost:5003/server-status
 (略)
 < HTTP/1.0 200 OK
 < Date: Thu, 01 Jul 2010 15:38:49 GMT
 < Server: Plack::Handler::Starlet
 < Content-Type: text/plain
 < Content-Length: 30
 < 
 BusyWorkers: 3
 IdleWorkers: 7

このMiddlewareを有効にするには、Plack::Builderを利用して

builder {
    enable "Plack::Middleware::ServerStatus::Lite",
        path => '/server-status',
        allow => [ '127.0.0.1', '192.168.0.0/16' ];
    $app;
};

のように設定します。pathはhttpで取得するする場合のURI。allowはアクセス制御用。何も書かないと一切アクセスできません。

このMiddlewareは新サービスで使ってもらえる予定で、リソース監視も当然行う予定になっています。あとはpsgi.multiprocessのflagぐらいは確認した方がいいかなぁと思っています。 ただpsgi.multiprocessがTRUEなmod_perl1で動かすとどうやらセグフォルするようですが。

このブログ記事について

このページは、Masahiro Naganoが2010年7月 2日 00:53に書いたブログ記事です。

ひとつ前のブログ記事は「鉄道博物館行ってプラレール買ってきた」です。

次のブログ記事は「CloudForecast Updates」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja