Gearmanによるキューイング
キューイングを使うメリット
ウェブアプリケーションを対象として考えています。
処理を分別できる。
今すぐ必要な処理、後回しにして良い処理、負荷が高い処理、負荷が低い処理を分別することができます。
ユーザがすぐに確認しなければならない処理、負荷が低くシステムの負担にならない処理は自分自身で処理し、後回しにして良い処理、負荷が高い処理はサーバにお願いして、違う人にやってもらえば、自分の仕事は極端に減ります。(ユーザにとって快適なウェブアプリケーションとなる。)
サーバプロセスがロードするライブラリが減る。
ウェブアプリケーションのプロセスないで重い処理を簡潔させてしまうと、待機プロセスすべてが、その重い処理に必要なモジュールやライブラリを読み込ませているので、その分メモリを占有してしまうらしいです。
これを別のプロセスで行えば、HTTPサーバ待機プロセスは軽くなります。
キューイングシステムの基本的な構成
+--------+ +--------+ +--------+ | Client | 仕事の依頼-> | Server | <-仕事を引き受ける | Worker | +--------+ +--------+ +--------+
ウェブアプリケーションで考えます。
ClientはCGIでしょう。Serverは今回はGearmanを使います。Workerは処理によって定義されます。
とりえあずインストール
FreeBSD
#cd /usr/ports/devel/p5-Gearman-Server #make install clean
起動
# gearmand --daemonize --pidfile=/var/run/gearmand.pid --port=7003
エラーでた。。。
/usr/local/bin/gearmandの先頭行が#!/usr/bin/local/perlになってた。
#!/usr/bin/perlに直して再度試すと、無事起動しました。
起動時のパラメータについて
- daemonize
- オプションを付けると個プロセスがforkされてデーモンとして稼働します。
- pidfile
- プロセスIDをファイルに記録することことができます
- port
- gearmandはデフォルトでポート7003番で稼働します。ひとつのサーバで複数のgearmandを立ち上げるにはポート番号を変更する必要があります。
gearmandサーバ停止方法
kill `cat /var/run/gearmand.pid`
テストWorker
#!/usr/bin/perl #gearmanテスト用ワーカー:) use strict; use warnings; use Gearman::Worker; use Storable qw(freeze thaw); use LWP::UserAgent; #ワーカーのインスタンス生成 my $worker = Gearman::Worker->new; # gearmandが稼働するサーバを指定 $worker->job_servers(qw/localhost:7003/); my $ua = LWP::UserAgent->new(timeout => 1); # get_site_statusジョブをサーバに登録 $worker->register_function( get_site_code=> sub{ my $job = shift; my %result = (); my @args = @{thaw($job->arg)}; for my $url (@args){ my $res = $ua->get($url); next unless $res->is_success; $result{$url} = $res->code; } return freeze(\%result); } ); # 処理待ちループ $worker->work while 1;
テストClient
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use Storable qw(freeze thaw); use Gearman::Client; my $client = Gearman::Client->new; $client->job_servers(qw/localhost:7003/); my @args = ( 'http://www.perl.org', 'http://cpan.org', 'http://c2.com/cgi/wiki', ); my $args = freeze(\@args); my %option = (); #ジョブを登録してその結果を受け取る my $result = $client->do_task(get_site_code => $args, \%option); my $deserialized = thaw($$result); print Dumper $deserialized;