Postfix ボトルネック分析


このドキュメントの目的

このドキュメントは管理者が時間および送信者や受信者ドメインでソートされた Postfix キューメッセージの分布を理解するのに役立つ qshape(1) プログラムについて記述しています。 qshape(1) は Postfix 2.1 ソースの "auxiliary" ディレクトリ以下にバンドルされています。

qshape(1) の出力を理解するためには、 様々な Postfix キューを理解することが役立ちます。この目的のために、 それぞれの Postfix キューディレクトリの役割がこのドキュメントの最後の方に ある "背景に関する情報: Postfix キューディレクトリ" セクションに簡単に 書かれています。

このドキュメントは以下の話題をカバーしています:

qshape ツールの紹介

メールの流れが遅かったりキューが予想外に大きい場合、問題に照準を 合わせるのに役立てるため、スーパーユーザ (root) で qshape(1) を実行してください。 qshape(1) プログラムは Postfix キューの内容を 表にして表示します。

例えば、以下の出力で "hold" キューにとらえられた spam の (ほとんどは騙られた) 送信者ドメイン 分布の上から 10 行を見て取れます:

$ qshape -s hold | head
                         T  5 10 20 40 80 160 320 640 1280 1280+
                 TOTAL 486  0  0  1  0  0   2   4  20   40   419
             yahoo.com  14  0  0  1  0  0   0   0   1    0    12
  extremepricecuts.net  13  0  0  0  0  0   0   0   2    0    11
        ms35.hinet.net  12  0  0  0  0  0   0   0   0    1    11
      winnersdaily.net  12  0  0  0  0  0   0   0   2    0    10
           hotmail.com  11  0  0  0  0  0   0   0   0    1    10
           worldnet.fr   6  0  0  0  0  0   0   0   0    0     6
        ms41.hinet.net   6  0  0  0  0  0   0   0   0    0     6
                osn.de   5  0  0  0  0  0   1   0   0    0     4

デフォルトでは、qshape はパフォーマンスを解析する際に最も関連する 注目すべきキューである、incomingactive キューの両方を 合わせた統計を示します。

別のキューのリストを要求することもできます:

$ qshape deferred | less
$ qshape incoming active deferred | less

これは deferred キュー の生存時間分布または incoming や active、 deferred キューを 合わせたものを表示します。

コマンドラインオプションは表示する "バケツ" の数や最も小さいバケツの 年齢制限、親ドメイン数の表示などを制御します。"-h" オプションは利用可能な スイッチの概要を出力します。

qshape を使ったトラブルシューティング

qshape の出力で大きな数があることは、特定のドメインが配送先の (もしくはンから来たと主張している) メッセージが多数あることを表して います。一目でどのドメインがキューの送信者または受信者の多数を占めて いるかや、いつ頃メールが爆発的に始まっていつ止まったかがわかるはずです。

問題の配送先や送信者ドメインは出力された表の左上の角近くに現れます。 active キューは最大 20000 ($qmgr_message_active_limit) メッセージまで対応できるということを覚えておいてください。この制限に 達したかどうかをチェックするには、次のコマンドを使います:

$ qshape -s active | head       (show sender statistics)

送信者数の合計が 20000 以下であれば、 active キューはまだ 飽和しておらず、送信者が大量にあるドメインは出力の上の方に示されます。

active キューは最大 20000 の受信者アドレス ($qmgr_message_recipient_limit) でも 制限されます。この制限の消耗度をチェックするには、次のコマンドを使います:

$ qshape active | head          (受信者の統計情報を示します)

大量にあるドメインを見つけたら、ログで問題のドメインに関連する 最近のメッセージを検索すると、時々役に立ちます。

# example.com への配送を見つける
#
$ tail -10000 /var/log/maillog |
        egrep -i ': to=<.*@example\.com>,' |
        less

# example.com からのメッセージを見つける
#
$ tail -10000 /var/log/maillog |
        egrep -i ': from=<.*@example\.com>,' |
        less

ある特定のキュー id について練習してみましょう:

# 特定のキュー id についての全てのメッセージを見つけます。
#
$ tail -10000 /var/log/maillog | egrep ': 2B2173FF68: '

ログに書かれたキューマネージャの警告メッセージも探してください。 これらの警告は混雑を緩和する戦略を提案するかもしれません。

$ egrep 'qmgr.*(panic|fatal|error|warning):' /var/log/maillog

全てに失敗したら、Postfix メーリングリストに助けを求めてみてください。 そのときにqshape(1) 出力の上10から20行を 含めることを忘れないでください。

例1: 健康なキュー

incomingactive キューだけを見ると、 通常の条件下では (混雑がない場合) incomingactive キューは空に近い 状態です。active キューが 過密でなければ、メールは入ってくるとほとんどすぐにシステムを離れてしまうか 遅延されます。

$ qshape        (incoming および active キューの状態を示します)

                 T  5 10 20 40 80 160 320 640 1280 1280+
          TOTAL  5  0  0  0  1  0   0   0   1    1     2
  meri.uwasa.fi  5  0  0  0  1  0   0   0   1    1     2

2つのキューを別々に見ると、 incoming キューは空か おそらく短時間だけ1つか2つのメッセージがあり、それに対して active キューはそれよりも いくらか長い時間、より多くのメッセージを抱えています:

$ qshape incoming

                 T  5 10 20 40 80 160 320 640 1280 1280+
          TOTAL  0  0  0  0  0  0   0   0   0    0     0

$ qshape active

                 T  5 10 20 40 80 160 320 640 1280 1280+
          TOTAL  5  0  0  0  1  0   0   0   1    1     2
  meri.uwasa.fi  5  0  0  0  1  0   0   0   1    1     2

例2: 辞書攻撃のバウンスであふれた deferred キュー

これはホスティングしている ドメインの一部に対してまだ受信者検証が使えないサーバからのものです。 検証が使えないドメインでの辞書攻撃はバウンスの後方散乱につながって しまいます。バウンスがキューを支配してしまいますが、適切にチューニング してあれば incomingactive キューを飽和させる ことはありません。大量の遅延メールは警告の直接の原因にはなりません。

$ qshape deferred | head

                         T  5 10 20 40 80 160 320 640 1280 1280+
                TOTAL 2234  4  2  5  9 31  57 108 201  464  1353
  heyhihellothere.com  207  0  0  1  1  6   6   8  25   68    92
  pleazerzoneprod.com  105  0  0  0  0  0   0   0   5   44    56
       groups.msn.com   63  2  1  2  4  4  14  14  14    8     0
    orion.toppoint.de   49  0  0  0  1  0   2   4   3   16    23
          kali.com.cn   46  0  0  0  0  1   0   2   6   12    25
        meri.uwasa.fi   44  0  0  0  0  1   0   2   8   11    22
    gjr.paknet.com.pk   43  1  0  0  1  1   3   3   6   12    16
 aristotle.algonet.se   41  0  0  0  0  0   1   2  11   12    15

示されているドメインはほとんどバルクメーラであり、全ての量が時間分布の 終わりに尾を引いています。これは短期間の到着速度が控えめであったことを 示しています。数字が大きかったりメッセージの生存時間が小さいほど、 現在の問題をより多く暗示しています。まだどこにも行かない古いメールは、 active および incoming キュー が少ない限りたいていは無害です。また、配送できない groups.msn.com は 集中辞書攻撃が今終わったという感じではなく、むしろ遅い一定速度の流れである ことが見てとれます。

$ qshape -s deferred | head

                     T  5 10 20 40 80 160 320 640 1280 1280+
            TOTAL 2193  4  4  5  8 33  56 104 205  465  1309
    MAILER-DAEMON 1709  4  4  5  8 33  55 101 198  452   849
      example.com  263  0  0  0  0  0   0   0   0    2   261
      example.org  209  0  0  0  0  0   1   3   6   11   188
      example.net    6  0  0  0  0  0   0   0   0    0     6
      example.edu    3  0  0  0  0  0   0   0   0    0     3
      example.gov    2  0  0  0  0  0   0   0   1    0     1
      example.mil    1  0  0  0  0  0   0   0   0    0     1

送信者の分布を見ると、予想通りほとんどのメッセージがバウンスであることが わかります。

例3: active キューの輻輳

この例は2004年2月の Postfix ユーザーズリストでの議論から持ってきました。 配送エージェントプロセス制限を非常に大きくしているにもかかわらず、active および incoming キューが大きくなって減らないという輻輳が報告されました。 このスレッドは以下にアーカイブ化されています: http://groups.google.com/groups?th=636626c645f5bbde

古いバージョンの qshape(1) を使うと、全てのメッセージがたったいくつかの 配送先に向けられたものであることが、すぐに割り出されました:

$ qshape        (incoming および active キューの状態を示します)

                           T   A   5  10  20  40  80 160 320 320+
                 TOTAL 11775 9996  0   0   1   1  42  94 221 1420
  user.sourceforge.net  7678 7678  0   0   0   0   0   0   0    0
 lists.sourceforge.net  2313 2313  0   0   0   0   0   0   0    0
        gzd.gotdns.com   102    0  0   0   0   0   0   0   2  100

"A" カラムは active キュー にあるメッセージ数を表しており、数字が書かれたカラムは deferred キューの合計を 表しています。10000 メッセージ (Postfix 1.x active キューサイズの制限) で active キューはいっぱいになります。incoming は急速に増えていきます。

問題の配送先が明らかに特定されたので、管理者はすぐに問題を見つけ、 修正しました。同じ情報をログから拾い集めるのはかなり困難です。 注意深く mailq(1) の出力を 読めば似たような結果は得られますが、キューで1メッセージずつ見ていたのでは 問題の大きさを評価するのはずっと困難です。

例4: 大量の配送先バックログ

あなたが大量のEメールを送った先のサイトがダウンしていたり遅かったり すると、メールメッセージは急速に deferred キュー か、 より悪い場合には active キュー が増えていきます。qshape の出力はその配送先ドメインに対して、問題の 始まった時間に重なる全ての経過時間バケツに、大きな数を表示するでしょう:

$ qshape deferred | head

                    T   5  10  20  40   80  160 320 640 1280 1280+
           TOTAL 5000 200 200 400 800 1600 1000 200 200  200   200
  highvolume.com 4000 160 160 320 640 1280 1440   0   0    0     0
             ...

ここで "highvolume.com" という配送先は遅延メールをため続けています。 incoming および active キューは問題 ありませんが、deferred キュー は1〜2時間前のある時から増え始め、今も増え続けています。

この大量メールの配送先がダウンしていなくて遅いのであれば、 active キューにも 同様な輻輳が見られるかもしれません。active キューの輻輳は警告を受ける 大きな要因です; メールを遅延したり、さらには access(5) で送信者に再送を試すように依頼する ルールを追加するべきかを確認するための測定が必要かもしれません。

全ての MX ホストが拒否したり "421 Server busy errors" となった接続が 連続的に頻発するという症状を大量メールの配送先が示しているようであれば、 一時的な性質のエラーであっても、キューマネージャに配送先を "死んでいる" としてマークさせることができます。配送先は $minimal_backoff_time タイマーの期限が切れた後で再び再試行されます。エラーの多発が頻繁であれば、 配送先が再び "死んでいる" とマークされる前に少量のEメールだけが配送 されるかもしれません。

このようなエラーの多発を最もよく頻繁に示すのが見られる MTA は Microsoft Exchange で、負荷が高くなると接続を拒否します。Exchange サーバの前にある プロキシウィルススキャナには "421" エラーとして拒否された接続を増殖させる ものもあります。

現在では anvil(8) サーバ (Postfix 2.1 には含まれません) を間違って設定する ことで、同様な異常な振る舞いを示すように Postfix を設定してしまうことが可能と なっていることに注意してください。定常状態の速度を制限するために anvil(8) を 使わないでください。これの目的は DoS を防ぐことであり、速度制限の設定値は 非常に寛大であるべきです。

長い目で見れば Postfix の死亡ホスト検出や並行処理の制御メカニズムが より "ノイズ" 耐性を持つように調整されることが望まれます。自分自身が大量の メールを頻繁に短期間のエラー多発を示す配送先に配送する必要性を感じた場合、 調整が難しい回避方法があります。

この驚くべき設定によって、同時数の合計が適切な (10-20 プロセス) の ままである一方で、連続した最大 200 のエラーを配送先死亡とマークせずに 耐えるという効果が得られます。このトリックは非常に限られた場面だけに 対するものです: 複数のエラーが多発する、高スループットが許容されるが エラー多発によって繰り返し窒息する、あるチャネルへの大量メールの配送。

Postfix プロセス制限が 1 に減らされた後でも負荷を配送先が扱えない 場合、最後の手段は配送試行ごとに短い遅延を挟むことです。

この解決策によって、Postfix smtp(8) クライアントが配送ごとに $smtp_connect_timeout 秒待つことが強制されます。この解決策は Postfix 接続管理の詳細による もので、SMTP 接続キャッシングが導入されたら更新する必要があります。

将来これらの問題に対するよりエレガントな解決策が見つかることを願って います。

背景に関する情報: Postfix キューディレクトリ

以下のセクションでは Postfix キューについて記述しています: その目的、 通常の振る舞いがどのように見えるか、および異常な振る舞いの診断方法。

"maildrop" キュー

Postfix sendmail(1) コマンドを使って 投函されたメッセージで、pickup(8) サービスに よって主要 Postfix キューに持ち込まれる前のメッセージは、 "maildrop" キューで 処理されるのを待ちます。Postfix システムが動いていないときでも メッセージを "maildrop" キューに加えることができます。Postfix が起動するとメッセージは 処理され始めます。

定期的もしくは postdrop(1) プログラムから 新着メールが通知されたときにキューディレクトリをスキャンする、シングル スレッドの pickup(8) サービスによって、 "maildrop" キューは排出 されていきます。 postdrop(1) プログラムは、 権限を持たない sendmail(1) プログラムが メールを "maildrop" キューに投入できるようにして、pickup(8) サービスにメールの到着を伝えられるようにする、setgid ヘルパーです。

主要 Postfix キューに入ってくる全てのメールは cleanup(8) サービスを使ってそうします。 cleanup サービスはエンベロープおよびヘッダの書き換え、ヘッダおよび 本体の正規表現チェック、自動 bcc 受信者処理や Postfix "incoming" キューへの メッセージの投入の保証を担当しています。

cleanup(8) ヘッダまたは本体の正規表現 チェックや利用可能な CPU リソースを全て消費するその他のソフトウェアで 過剰に CPU を消費しない限り、Postfix のパフォーマンスはディスク I/O に 縛られます。cleanup(8) サービスは成功を返す 前にメッセージを安定したストレージに置かなければいけないため、 pickup(8) サービスがメッセージをキューに 投入する速度の大部分はディスクアクセス時間によって決まります。同じことが、 postdrop(1) プログラムが "maildrop" ディレクトリにメッセージを書き込むことにも当てはまります。

pickup サービスはシングルスレッドであるため、cleanup サービスの ディスク I/O レイテンシ (無視できない場合には + CPU) との相関を超えない 速度で、同時に1つずつしかメッセージを配送することができません。

このキューでの輻輳はローカルメッセージの投函速度が過剰であったり、 もしかしたら過剰な body_checks による cleanup(8) サービスで過剰に CPU が 消費されていることを示しています。

一旦 active キューが いっぱいになると、cleanup サービスはそれぞれのメッセージ後ごとに $in_flow_delay の間止まる ことで、メッセージの投入を遅くしようとします。この場合、 "maildrop" キューの輻輳は それだけの問題ではなく、下流の輻輳という結果になるかもしれないことに 注意してください。

また、大量のメールを pickup(8) サービスを 使って配送しようとすべきでないことに注意してください。規模の大きな サイトはスキャンされたメールを Postfix sendmail(1)postdrop(1) を使って再投入するコンテンツ フィルタの使用を避けなければいけません。

ローカルで投かんされたメールの到着速度が速いのは、捕まえられない転送 ループや通知プログラムの暴走を示しているかもしれません。ローカルメールの 投入量を適度なレベルに保つようにしてください。

"postsuper -r" コマンドは選択したメッセージを再処理するために "maildrop" キューに 置くことができます。これは古い content_filter 設定をリセット するのに最も便利です。多数のメッセージに "postsuper -r" の使用を要求 すると、明らかに "maildrop" キューサイズの急激な増加を引き起こします。

"hold" キュー

管理者はメッセージが自動的に通常の処理を迂回して無期限に "hold" キューに置かれる ように "smtpd" access(5) ポリシーや cleanup(8) ヘッダ/本体チェックを定義する ことができます。 "hold" キューに置かれたメッセージは管理者が介入するまで そこにとどまります。"hold" キュー の中にメッセージに対しては定期的な配送試行はなされません。手動で "deferred" キューに メッセージを放出するには、postsuper(1) コマンドを使うことができます。

メッセージは通常のキューの最大寿命 (配送されなかったメッセージが 送信者にバウンスで返される時) を超えても潜在的に "hold" キューにとどまります。 このような "古い" メッセージが "hold" キューから解放される必要がある場合、たいていそれらは "maildrop" キューに 移されて、その結果メッセージは新しいタイムスタンプを取得して1回以上の 配送の機会が与えられることになります。"若い" メッセージは直接 "deferred" キューに移されます。

"hold" キュー は Postfix の パフォーマンスにおいてあまり大きな役割を持たず、spam や悪意を持った ソフトの追跡する際に、"hold" キューの監視はより密接に動機づけられます。

"incoming" キュー

Postfix キューに入ってくる新しいメールは全て cleanup(8) サービスによって "incoming" キューに書き 込まれます。新しいキューファイルは "postfix" ユーザによって所有される、 アクセスビットマスク (またはモード) が 0600 のファイルとして作られます。 その後の処理に向けてキューファイルの準備ができると、 cleanup(8) サービスはキューファイルモードを 0700 に変更して、キューマネージャにメールが新たに着いたことを通知します。 キューマネージャはモードが 0600 であって cleanup によってまだ書き込まれて いる、不完全なキューファイルを無視します。

"active" キューのリソース 制限が超過していなければ、キューマネージャは incoming キューを スキャンして、新しいメールを active キューキューに持ち込みます。デフォルトでは、 active キュー最大 20000 メッセージまで対応します。active キューメッセージ制限に達すると、 キューマネージャは incoming (および deferred、以下参照) キューの スキャンを停止します。

通常の条件下では、incoming キューは (モードが 0600 のファイルが) 空に近い状態で、キュー マネージャは利用可能になるとすぐに新しいメッセージを active キューに持ち込む ことができます。

キューマネージャが active キューにメッセージを持ち込む速度以上にメッセージの入力速度が 速くなると、incoming キュー は大きくなります。キューマネージャが遅くなる主な要因は trivial-rewrite サービスによる transport の問い合わせです。キューマネージャがいつも 遅くなっているようであれば、transport の検索に "遅い" 検索サービス (MySQL、LDAP、...) を使わないようにすることや、検索サービスを提供する ホストの高速化を検討してください。

キューマネージャが遅れ始めたときに入力速度を抑えるのに in_flow_delay パラメータが 使われます。cleanup(8) サービスはキュー マネージャから "トークン" を得られないと、新しいキューファイルを作る前に $in_flow_delay 秒の間、一時 停止します。

cleanup(8) のプロセス数はほとんどの場合、 SMTP サーバの並列数によって制限されているため、最大毎秒 "SMTP の接続数"/ $in_flow_delay メッセージだけ入力速度が出力速度を超えます。

デフォルトの 100 というプロセス制限と 1s という in_flow_delay では、1つの 暴走した投入者を毎秒1メッセージに制限するには結合が十分に強いのですが、 同時に多数のソースから来る過剰な入力を逸らすほどには強くありません。

サーバが複数の方向から叩かれている場合で、 in_flow_delay キューが大きく なっているのに active キューが いっぱいではなく、trivial-rewrite サービスが速い transport 検索メカニズムを 使っている場合に限って、in_flow_delay を10秒に上げることを検討してください。

"active" キュー

キューマネージャは配送エージェントのスケジューラです; 指定された リソース制限内で、全ての配送先に対してメールを速く正確に配送させるために 働きます。

active キューは オペレーティングシステムのプロセス実行キューと似たようなものです。 active キューにある メッセージは送信される準備ができていますが (実行可能)、送られている最中 (実行中) である必要はありません。

ほとんどの Postfix 管理者は "active" キューはディスク上の ディレクトリと考えていますが、実際の "active" キューとは キューマネージャプロセスのメモリ内にある、データ構造セットのことです。

"maildrop" や "hold"、 "incoming"、"deferred" キューにあるメッセージ (以下参照) はメモリを占有しません; これらは安全に ディスク上に保管され、処理される順番を待っています。 "active" キューにある メッセージのエンベロープ情報はメモリ内で管理され、キューマネージャが 全体のスケジューリングをおこなえるようにし、active キューにある適切な メッセージに利用可能な配送エージェントプロセスを割り当てます。

active キュー内では、 (受信者が複数の) メッセージは同じ transport/nexthop の組み合わせを 共有する受信者のグループに分割されます; グループの大きさは transport の 並列受信者数制限で抑えられます。

(1つ以上のメッセージからできた) 受信者が複数のグループ は共通の transport/nexthop の組み合わせを使って配送されるためにキューに入れられ ます。transport に対する配送先の並列制限によってそれぞれの nexthop への 同時配送試行数は抑えられます。同時受信者制限が 1 の transport は 特別です: これらは nexthop ではなく実際の受信者アドレスによってグループ化 されます。それによってドメインごとの並列制限ではなく受信者ごとの 並列制限を有効にします。受信者ごとの制限はリモートサーバに転送するとき よりも、メールボックスへの最終配送のときに適しています。

一つ以上の配送先で流れが対応する入力よりも遅くなると、 active キューキュー マネージャは配送先が死亡しているとマークして、その配送先への全ての メールを配送エージェントに割り当てようとせず、すぐに遅延します。 この場合、メッセージはすぐに active キューから離れ、deferred キューに行き着きます。そうではなく単に遅いだけで あったり、到着速度を過剰にする問題がある場合には、active キューは増え続け 輻輳している配送先へのメールに支配されることになります。

輻輳を減らす方法は入力速度を下げるかスループットを上げることの どちらかだけです。スループットを上げるには並列数を上げるか配送の レイテンシを下げる必要があります。

大規模サイトでは、鍵となるチューニングパラメータは "smtp" および "relay" transport に割り当てられる "smtp" 配送エージェント数です。大規模サイトは 多くの異なる配送先に送る傾向があり、その大多数がダウンしていたり遅かったり するかもしれないため、利用可能な配送エージェントをかなり少なくすると 遅いサイトを待つものでふさがれることになります。また、世界中に向けられた メールは SMTP コマンド応答のレイテンシが大きくなってしまうので、配送 エージェントをより多くすることによってのみメッセージの高いスループットは 得られます。

100 というデフォルトの "smtp" プロセス制限はほとんどのサイトでは 十分であり、低いバンド幅で接続しているサイトでは低くする必要さえあるかも しれません (ネットワークのパイプがいっぱいなのに並列数を増やすのは 無駄です)。"忙しくない" システム (CPU、ディスク I/O および ネットワークが使い尽くされていない) でキューが大きくなっている場合、 残る輻輳の理由は高い平均レイテンシに直面した並列数の不足です。外行きの SMTP 接続数 (ESTABLISHED または SYN_SENT のどちらか) がプロセス制限に 達していて、メールがゆっくりしか流れずシステムやネットワークの負荷が 高くなければ、"smtp" や "relay" プロセス制限を引き上げてください!

特に "relay" transport に対しては、SMTP 接続タイムアウトを短く (1-5 秒) して同時配送制限をデフォルトよりも高くすることを検討して ください。大規模サイトの N 個の MX ホストのうちの1つがダウンしていて 応答しない場合に予想されるレイテンシを計算して、設定された同時数を このレイテンシで割った値が必要な定常状態メッセージ速度を超えている ことを確認してください。もしあなたが配送先を管理しているのであれば、 MX ホストグループの前にロードバランサを設置することを検討してください。 ロードバランサはアップタイムがより長く、個々の MX ホストの障害を 隠蔽できます。

必要ならば、大規模な配送先専用のカスタム transport を用意して 調整してください。

他によくある輻輳の原因として、 deferred キュー全体の不当な flush があります。deferred キューは配送に失敗しそうであったり、配送に 失敗するほど遅い (タイムアウト) メッセージを保持しています。これは、大きな deferred キュー に対する リアクション (flush すること!) はどちらかといえば非生産的であり、問題を 悪化させるかもしれない、ということを意味します。 deferred キューの 中身のほとんどがすぐに配送可能になりそう (例えば、故障後の relayhost バックアップ) と いうのでなければ、deferred キューを flush しないでください!

キューマネージャが再起動する際には、active キューにメッセージがすでに あるかもしれませんが、メモリ内の "実際の" active キューは空で あることに注意してください。メモリ内の状態を回復するために、キュー マネージャは全ての active キュー メッセージを incoming キュー に戻し、それから再び通常の incoming キュースキャンを使って active キューを埋めます。 メッセージ全てを行ったり来たりさせるプロセスが再び transport テーブル (trivial-rewrite(8) 解決サービス) 検索をおこない、メッセージを再びメモリに持ち込むというのは負荷が高い ものです。頻繁にキューマネージャを再起動するのは絶対に避けてください。

The "deferred" キュー

メッセージの配送可能な全ての受信者が配送されて、ある受信者へは一時的な 理由 (後で成功するかもしれない) で失敗した場合、メッセージは deferred キューに 置かれます。

キューマネージャは deferred キューを定期的にスキャンします。スキャンの間隔は queue_run_delay によって 制御されます。deferred キュー スキャンの進行中に、incoming キュースキャンも進行中であれば (理想的には incoming キューは小さい はずなので、これも短いはずです)、キューマネージャは新しい"incoming" メッセージと新しい "deferred" メッセージを交互にキューに入れます。この "ラウンドロビン" 戦略は incomingdeferred キューの どちらの枯渇も防ぎます。

1回の deferred キュー スキャンでは少しの deferred キューだけを active キューに入れて 再試行します。これは deferred キュー にあるそれぞれのメッセージには遅延されたときに "冷却" 期間が 割り当てられるためです。これはキューファイルの修正時間を未来にワープ させることで実現しています。修正時刻にまだ達していないキューファイルは 再試行を受ける権利がありません。

"冷却" 期間は最低 $minimal_backoff_time、 最大 $maximal_backoff_time です。次の再試行時刻はメッセージのキューの滞在時間を2倍して制限内に なるように上下に調整することで設定されます。これは若いメッセージは始めは 古いメッセージよりも頻繁に再試行されるということです。

大規模サイトのせいで定期的に deferred キューが大きくなるのであれば、最初の失敗では十分に短い遅延で、 複数回失敗した後はより長い遅延となるようにして古いメッセージの再転送 速度を減らし、active キュー内の 以前に遅延されたメールの量を減らすために queue_run_delayminimal_backoff_timemaximal_backoff_time を設定するのが実用的かもしれません。

deferred キューが 大きくなる原因は、SMTP 入力の場面で受信者の確認の失敗がよくあります。 スパマーは日常的に応答できないアドレスから辞書攻撃を仕掛けるため、 無効な受信者アドレスへのバウンスが deferred キューを 詰まらせてしまいます (そしてその容量が大きくなるにつれて active キューも詰まらせて しまいます)。 local_recipient_mapsrelay_recipient_maps パラメータを使って、受信者の有効性を確認することを強く推奨します。

大量の遅延メールがあるホストがしばらくダウンすると、 deferred キュー全体が 同時に再試行時間に達する可能性があります。これにより、ホストが復活したら active キューを完全に いっぱいにしてしまいかねません。輻輳の短い爆発の後にメッセージが再び 遅延されると、およそ maximal_backoff_time 秒ごとにこの現象が繰り返されるかもしれません。理想としては、繰り返し完全に deferred キューが flush される確率を減らすために、将来 Postfix は再試行 時間にランダムなオフセットを加えることになるでしょう (もしくは戦略を 組み合わせるでしょう)。

クレジット

The qshape(1) プログラムは Morgan Stanley の Victor Duchovni によって開発され、またこのドキュメントの最初のバージョンも 彼が書きました。