最近のwebappはいかにイベントループを止めないかが重要です。非同期処理です。重い処理はjobqueueでwebappのプロセスから投げて外してあげるというのがレスポンス向上にかかせません。PerlのjobqueueにはTheshwartzやGearmanが有名どころみたいです。調べてみたところ、すぐ処理を行うならGeramanらしいですが、Gearmanも他にプロセスをあげるようなのでDBを使ってることで信頼性が高いTheSchwartzを導入することにしました。
インストール
まずはPerlモジュールをダウンロードする。
$ cpanm TheSchwartz
次にスキーマファイルをダウンロード。
$ wget http://cpansearch.perl.org/src/SIXAPART/TheSchwartz-1.10/doc/schema.sql
スキーマのファイルからデータベースを作成する
$ mysql -uroot -p
mysql> create database TheSchwartz
mysql> grant all on TheSchwartz.* to <user>@localhost identified by “xxxx”;
$ mysql -u<user> -p -DTheSchwartz < ./schema.sql
JobQueueクラスを作ります。job9->sendmail($info)でジョブを投げます。
package JobQueue;
use Mouse;
use strict;
use warnings;
use TheSchwartz;
has client => (
is => 'ro',
isa => 'TheSchwartz',
lazy => 1,
builder => '_build_client',
);
sub _build_client {
my $self = shift;
return TheSchwartz->new(
databases => [{
dsn => 'dbi:mysql:TheSchwartz',
user => ‘<user>’,
pass => ‘xxxx’,
}],
verbose => 1,
);
}
sub sendmail {
my ($self, $info) = @_;
$self->client->insert(MailWorker => $info);
}
1;
ワーカーのスクリプトは下のようになります。postfixがCentOSで走っているのでMail::Mailerを使用してメール送信を行うようにしました。
#MailWorker.pl
package MailWorker;
use strict;
use warnings;
use base qw( TheSchwartz::Worker );
use Data::Dumper;
use Mail::Mailer;
use utf8;
use Encode;
sub work {
my ($class, $job) = @_;
print "process...\n";
print Dumper $job->arg;
my $info = $job->arg;
my $subject = encode('MIME-Header-ISO_2022_JP', $info->{'title'});
my $url = $info->{'url'};
my $body = “....”
my $mailer = new Mail::Mailer 'smtp', Server => 'localhost';
$mailer->open(
{To => $info->{'email'},
From => ‘my@domain.com',
Subject => $subject,
}
);
print $mailer $body;
$mailer->close;
$job->completed();
}
package main;
use strict;
use warnings;
use TheSchwartz;
my $client = TheSchwartz->new(
databases => [{
dsn => 'dbi:mysql:TheSchwartz',
user => ‘<user>’,
pass => ‘xxx’,
}],
verbose => 1, # ログを出力
);
$client->can_do('MailWorker');
my $interval = 10; # default is 5
$client->work($interval);
workerプロセスを起動してジョブを待ち受けます。
$ perl MailWorker.pl
下記みたいな感じでジョブを投げたらメールを送れました!^_^
my $job9 = JobQueue->new();
my $info = { email => ‘hoge@hoge.com’,,, }
$job9->sendmail($info);
Reference :