queuegroup - Queue回りの最適化

sendmail 8.12からqueuegroupが導入されました。 queueというのは、メールが送信されるとき、一旦ため置かれる場所で、名前 の通り、前から順番に処理されます。順調に配送できてるならいいのですが、 相手ホストが落ちてる、DNSがうまく引けないなどの理由でうまく送信できな いと、そのタイムアウトを待って次のメッセージの処理にいくので、どうして もメッセージ配送が遅くなってしまいます。このqueueを並列化すれば、ある queueがつまっても別のqueueには影響しないので、別queueのメッセージは早 く配送されて幸せになれます。 実際、Postfixは配送を早くするため、宛て先の頭のアルファベットごとに異 なるqueueを持っていたような気がします(うろ覚え)。

queuegroup関連の機能で、以下の機能が実現できます。

使ってみよう

sendmail.cf (.mcではないので注意)をさわります。いきなり /etc/mail/sendmail.cfをいじるのではなく、そのコピーをいじってください。

まず、デフォルトのQueueの設定をします。

O QueueDirectory=/var/spool/mqueue/dir*

こうすると、/var/spool/mqueue/dir* のディレクトリすべてがデフォルトの queueグループとなります。例えば /var/spool/mqueue/dir0 〜 dir4 の5つの ディレクトリを作っておくと、デフォルトのqueueが使われるたびにランダム にdir0 〜 dir4のいずれかが選択されます。実は、多くのサイトにとってはこ れだけで十分かもしれません。

#dir0 〜 dir4のpermissionとownerをmqueueと同じにしておくこと (sendmailを実行するユーザ名がsmmspならば、それぞれownerをsmmsp, パーミッ ションを700にしておく)

続いて、宛て先や送り主によるqueueを設定します。各queueのグループには名 前をつけなければなりません。例えば、/var/spool/mqueue/puniにpuniという 名前のqueuegroupを作るなら、

Qpuni,P=/var/spool/mqueue/puni

とします。Q(queue name),P=(path)という構文です(他にオプションがいろい ろありますが、それはdocumentを見てください)。ここで、各queueはデフォル トのqueueのディレクトリ以下になければなりません。また、同じディレクト リを二重に定義してはいけません。つまり、例えば

O QueueDirectory=/var/spool/mqueue/*
Qpuni,P=/var/spool/mqueue/puni

という定義はだめ(puniのqueueがデフォルトqueueの設定に含まれてしまう)。

これでqueueそのものができあがったわけですが、どういう条件でどのqueueを 使うのか、ということを定義しなければなりません。そのために、queuegroup というルールセットを書きます。例えば、

Squeuegroup
Rmimori@puni.net $#puni
とすると、mimori@puni.net宛てのメッセージについては、(先に定義した) puniというqueuegroupを利用します。

まとめに、もうちょっと複雑な例を挙げます。

O QueueDirectory=/var/spool/mqueue/*
Qmimori,P=/var/spool/mqueue/mimori
Qpuni,P=/var/spool/mqueue/puni

Squeuegroup
Rmimori@puni.net $#mimori
R$*@puni.net $#puni

こうすると、mimori@puni.net宛てはmimori, それ以外のpuni.net宛てはpuni, それ以外はデフォルトのqueuegroupを利用します。

access.dbを用いた設定

queuegroupの設定は、実はaccess.dbを用いても行うことができます(そして、 その方が簡単です)。なお、access.dbの別の利用方法として、ユーザごとの受信制限などにも用いることがで きます。

準備
sendmail.mc に以下の2行を書きます。
FEATURE(`access_db')
FEATURE(`queuegroup')

上がaccess.dbを使うという設定、下がaccess.dbでqueuegroupに関する設定を 行う、という設定です。

もちろん、Queuegroupそのものの設定は必要です。.mcでは、「O QueueDirectory」の設定はできますが、「Qhoge」の設定は出来ないようなの で、例えばこんな風に書きます。

LOCAL_CONFIG
Qpuni,P=/var/spool/mqueue/puni

そして最後に、queuegroup選択の条件を示すデータベースを作ります。 accessというファイルを作り、

QGRP:mimori@puni.net mimori
QGRPpuni.net puni
(ただし、puni.netとmimoriの間などの空白はtabにしてください)
と書いて
makemap hash access.db < access
とするとaccess.dbができ、設定完了となります。

関連する設定

MaxQueueChildren

Queueを処理するときに同時に動く全プロセス数で、これを大きくするとqueue の処理が早くなりますが、マシンのリソースがたくさん必要になります。 この値はqueuegroupごとの値ではなく、それらの総和です。

この値を50にする場合、sendmail.cfなら「O MaxQueueChildren=50」、.mc なら 「define(`confMAX_QUEUE_CHILDREN',`50')」とします。

Host Status

もともと、sendmailは接続しようとしたホストについて、接続の成功、失敗を キャッシュして後の接続に役立てる仕組みがあります。この情報は、普通の設 定ではメモリ上に蓄積されますが、sendmailによる処理が並列する場合には、 キャッシュが有効に利用できなくなってしまいます。この並列処理している sendmail間で接続情報を共有するため、ファイルに置くように設定することも できます。

これを/var/spool/hoststatにおくなら、sendmail.cfでは以下の2行を追加し ます。ちなみに、下の行(SingleThreadDelivery)は、ある1つのホストに対し て同時に2つ以上のsmtpコネクションをはらないようにする設定で、これによっ て多数のsmtpコネクションを同時にはってしまうことによる相手ホストの負荷 上昇を防ぐことが出来ますが、配送は遅くなるので、これを設定するかどうか は良く考えた方が良いでしょう。なお、HostStatusDirectoryを設定しないと、 SingleThreadDeliveryはTrueに設定できません。

O HostStatusDirectory=/var/spool/hoststat
O SingleThreadDelivery=True

また、.mcなら以下の通り。

define(`confHOST_STATUS_DIRECTORY',`/var/spool/hoststat')dnl
define(`confSINGLE_THREAD_DELIVERY',`True')dnl

これで接続ホストに関する情報をキャッシュ、共有できます。

以上の設定をまとめると、こんな風になります。

VERSIONID(`$Id: test.mc,v 1.1 2002/09/07 09:32:26 s-v Exp s-v $')
OSTYPE(bsd4.4)dnl

define(`QUEUE_DIR',`/var/spool/mqueue/dir*')dnl
define(`confMAX_QUEUE_CHILDREN',`50')dnl
define(`confHOST_STATUS_DIRECTORY',`/var/spool/hoststat')dnl
define(`confSINGLE_THREAD_DELIVERY',`True')dnl

MAILER(local)dnl
MAILER(smtp)dnl

LOCAL_CONFIG
Qpuni,P=/var/spool/mqueue/puni

Return


Mimori Yuki <mimori@puni.net>
$Id: qgroup.html,v 1.1 2002/09/07 09:32:26 s-v Exp s-v $