Gearmanによるキューイング

公式:http://gearman.org/

キューイングを使うメリット

ウェブアプリケーションを対象として考えています。

処理を分別できる。

今すぐ必要な処理、後回しにして良い処理、負荷が高い処理、負荷が低い処理を分別することができます。
ユーザがすぐに確認しなければならない処理、負荷が低くシステムの負担にならない処理は自分自身で処理し、後回しにして良い処理、負荷が高い処理はサーバにお願いして、違う人にやってもらえば、自分の仕事は極端に減ります。(ユーザにとって快適なウェブアプリケーションとなる。)

サーバプロセスがロードするライブラリが減る。

ウェブアプリケーションのプロセスないで重い処理を簡潔させてしまうと、待機プロセスすべてが、その重い処理に必要なモジュールやライブラリを読み込ませているので、その分メモリを占有してしまうらしいです。
これを別のプロセスで行えば、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;

コーディングの際の注意事項

引数はスカラー値しか渡せません。

よって複雑な引数を渡したいときは、スカラー値にシリアライズして渡してやらなければなりません。
上記の例ではStorableを使用しています。