大量のメルマガなどを配信する場合、サーバのスペックによってMTAにキューを投げる
間隔(時間)を調整したり、他サーバをリレーさせたりするのが一般的。
ただこれらをブラウザから行なうと、いつまでもブラウザが開放されず、timeoutに
なってしまう。
なのでこういった場合は、時間のかかる処理をバックグラウンドにまわして、ブラウザは
さっさと開放する。
(「まぐ●ぐ!」などで、即時配信した後、すぐ管理画面に戻れるのはそういった
仕掛けがあるからです。)
perlでバックグラウンド実行を行なうには、fork()関数か、ithreadを使う場合が多い
らしい。
速さから言えばithreadのほうが速いらしいが、ithreadは必要なモジュールが標準でセットされてないので、お手軽なのはfork()。←現在は標準になってる模様
-------------------------------------------------------------------
#!/usr/bin/perl -w
$| = 1; #バッファ制御
sub start_imme{ #### 即時配信処理
######## ここらでパラメータ受け取り
########## ここらでメールデータをセット
########### ここらでMIMEフォーマットなど
########## ここらで配信する読者をセット
my @user_no = "配信するユーザ番号など";
if(@user_no == 0){
&error("配信可能な読者がいませんでした。");
}
######## ここからバックグラウンド処理開始
else{
FORKLABEL: { ##ラベル開始
if( $pid = fork ) { # 子プロセス生成。$pidにはforkのプロセスNoが返る
###### ここは親プロセスのみで実行
&show_imme_done(); ###「配信完了」などの表示をここで出力
###### 標準出力を閉じてブラウザ開放
close(STDOUT);
wait; ###### 子プロセスを待たないと子がゾンビになります
}elsif (defined $pid) {
###### ここは子プロセスのみで実行
###### 標準出力を閉じてブラウザ開放
close(STDOUT);
###### ここらから時間のかかる処理
######### メール送信
my $mass = 10; # 一斉送信数
my $interval = 5; # 待ち時間
my $i = 0;
my $bench = time;
while($i < @user_no){
&sendmail(
$mail_to,
$mail_from,
$reply_add,
$envelope_add,
$sbj,
$body
);
if($i){
if($i % $mass == 0){
sleep $interval;
}
}
$i++;
}
my $req_time = time - $bench;
########## この辺で配信履歴の保存処理など
}elsif ( $! =~ /No more process/) {
# 生成するプロセスが多すぎる時は、少し待って再チャレンジ。
sleep 10;
redo FORKLABEL;
}else {
##### ここにくるようなら、perl自体動かないはず。
die "forkがサポートされていません。サーバ管理者にお問い合わせください。";
}
} # ラベルの閉じ
}
exit;
}
間隔(時間)を調整したり、他サーバをリレーさせたりするのが一般的。
ただこれらをブラウザから行なうと、いつまでもブラウザが開放されず、timeoutに
なってしまう。
なのでこういった場合は、時間のかかる処理をバックグラウンドにまわして、ブラウザは
さっさと開放する。
(「まぐ●ぐ!」などで、即時配信した後、すぐ管理画面に戻れるのはそういった
仕掛けがあるからです。)
perlでバックグラウンド実行を行なうには、fork()関数か、ithreadを使う場合が多い
らしい。
速さから言えばithreadのほうが速いらしいが、
-------------------------------------------------------------------
#!/usr/bin/perl -w
$| = 1; #バッファ制御
sub start_imme{ #### 即時配信処理
######## ここらでパラメータ受け取り
########## ここらでメールデータをセット
########### ここらでMIMEフォーマットなど
########## ここらで配信する読者をセット
my @user_no = "配信するユーザ番号など";
if(@user_no == 0){
&error("配信可能な読者がいませんでした。");
}
######## ここからバックグラウンド処理開始
else{
FORKLABEL: { ##ラベル開始
if( $pid = fork ) { # 子プロセス生成。$pidにはforkのプロセスNoが返る
###### ここは親プロセスのみで実行
&show_imme_done(); ###「配信完了」などの表示をここで出力
###### 標準出力を閉じてブラウザ開放
close(STDOUT);
wait; ###### 子プロセスを待たないと子がゾンビになります
}elsif (defined $pid) {
###### ここは子プロセスのみで実行
###### 標準出力を閉じてブラウザ開放
close(STDOUT);
###### ここらから時間のかかる処理
######### メール送信
my $mass = 10; # 一斉送信数
my $interval = 5; # 待ち時間
my $i = 0;
my $bench = time;
while($i < @user_no){
&sendmail(
$mail_to,
$mail_from,
$reply_add,
$envelope_add,
$sbj,
$body
);
if($i){
if($i % $mass == 0){
sleep $interval;
}
}
$i++;
}
my $req_time = time - $bench;
########## この辺で配信履歴の保存処理など
}elsif ( $! =~ /No more process/) {
# 生成するプロセスが多すぎる時は、少し待って再チャレンジ。
sleep 10;
redo FORKLABEL;
}else {
##### ここにくるようなら、perl自体動かないはず。
die "forkがサポートされていません。サーバ管理者にお問い合わせください。";
}
} # ラベルの閉じ
}
exit;
}

コメントする