このドキュメントにあるヒントやtipsはすでに動いているPostfixシステムの パフォーマンスを向上するのに役立ちます。あなたのPostfixシステムがメールを 送信したり受信したりできないのであれば、 DEBUG_README ドキュメントを手引きとして 使い、まずその問題を解決する必要があります。
外部コンテンツフィルタのパフォーマンスをチューニングするには、まず FILTER_README と SMTPD_PROXY_README ドキュメントの 情報を読んでください。そしてコンテンツフィルタコードのレイテンシをなくす ようにします。できるだけ遅延が大きかったり遅延のバラツキが大きい外部 データソースへの問い合わせを避けるようにしてください。CPU/メモリを使い 果たさないように、コンテンツフィルタは並列数を小さくして走らせますが、 レイテンシがあると、コンテンツフィルタのスループットは苦しむことに なるでしょう。大容量環境では RBL 検索や複雑なデータベース検索などを 避けるべきです。
メール受信のパフォーマンスに関する話題:
メール配送のパフォーマンスに関する話題:
他のPostfixパフォーマンスチューニングに関する話題:
以下のツールは人工的に負荷をかけてメールシステムのパフォーマンスを 測定することができます。これらは通常Postfixとともにはインストール されません。
QSHAPE_README ドキュメントの maildrop キュー や incoming キュー、 and active キュー の 議論を読んで理解してください。
DNS検索による速度の低下を抑えるため、ローカルにネームサーバを 走らせてください。複数のPostfixシステムを動かす場合、上流ネットワークに 検索するアクセス数を増やさないようにするために、それぞれのローカル ネームサーバを共有した転送サーバに向けてください。
ドメインフィルタを指定して不必要なLDAP検索をなくしてください。 これによりリモートドメインのアドレス検索がなくなり、また部分アドレスの 検索もなくなります。詳細は ldap_table(5) を参照してください。
SMTPクライアントに対するPostfixの応答が遅い場合:
DEBUG_README ドキュメントに書かれている 明らかなトラブルの兆候を探し、 まずはその問題をなくしてください。
header_checks と body_checks パターンを無効に して、問題が消えたかどうかを見てください。
DEBUG_README ドキュメントに書かれているように chroot 動作を無効にして、 問題が消えたかどうかを見てください。
PostfixがSMTPクライアントを "unknown" とログに記録している 場合、ネームサービスに問題があります: ネームサーバが悪い、または resolv.conf ファイルに間違った情報がある、または DNS リクエストやその 応答をブロックするパケットフィルタがあります。
smtpd(8) のプロセス数が master.cf で 指定されたプロセス制限に達していたら、新しいSMTPクライアントは プロセスが利用可能になるまで待たなければいけません。メモリが許せば プロセス数を増やします。"Postfixプロセス数の チューニング" に書かれた指示も見てください。
Postfixバージョン2.0以前では、smtpd(8) サーバはSMTPクライアントにエラーを報告する前に一時停止します。この アイディアはタール抗 (tar pitting) と呼ばれます。しかし、これらの遅延は Postfixも遅くします。smtpd(8) サーバの応答が 遅いとセッションに時間がかかり、その結果負荷をさばくのにより多くの smtpd(8) サーバプロセスが必要となって しまいます。Postfix smtpd(8) サーバプロセス 制限に達すると、新しいクライアントはサーバプロセスが利用可能になるまで 待たなければいけません。これはクライアントすべてのパフォーマンスが悪くなる ことを意味します。
遅延を無効にすることで smtpd(8) サーバの エラー応答の扱いを高速化することができます:
/etc/postfix/main.cf: # Postfix 2.1 では不要です smtpd_error_sleep_time = 0
上の設定を使うと、Postfix 2.0以前では同じSMTPサーバプロセス数で より多くのSMTPクライアントにサービスを提供できます。次のセクションでは、 Postfixが多数のエラーを出すクライアントをどう扱うかについて記述して います。
Postfix smtpd(8) サーバはセッションごとの エラーカウントを管理しています。メッセージの転送に成功するとエラー カウントはリセットされ、クライアントの要求が認識できなかったり実装されて いなかったり、クライアントの要求が アクセス制限を犯す場合、他の エラーが起こった場合には、エラーカウントは増加します。
セッションごとのエラーカウントが増加するにつれ、 smtpd(8) サーバは振る舞いを変えて応答に遅延を 入れ始めます。これはリソースの使用を制限するために暴走したクライアントを 遅くするという考えです。この振る舞いはPostfixのバージョンに依存します。
重要: これらの遅延はPostfixも遅くします。遅延を大きく設定しすぎると、 同時SMTPセッションの数が増加して smtpd(8) サーバプロセス制限に達し、新しいSMTPクライアントは smtpd(8) サーバプロセスが利用可能になるまで 待たなければいけません。
Postfixバージョン2.1以降:
エラーカウントが $smtpd_soft_error_limit (デフォルト: 10) に達すると、Postfix smtpd(8) サーバは非エラーおよびエラー応答のすべてを $smtpd_error_sleep_time 秒 (デフォルト: 1秒) だけ遅らせます。
エラーカウントが $smtpd_hard_error_limit (デフォルト: 20) に達すると、Postfix smtpd(8) サーバは接続を切ります。
Postfixバージョン2.0以前:
エラーカウントが $smtpd_soft_error_limit (デフォルト: 10) 以下のときは、Postfix smtpd(8) サーバは応答すべてを $smtpd_error_sleep_time (Postfix 2.0 では1秒、Postfix1.1 以前では5秒) 遅らせます。
エラーカウントが $smtpd_soft_error_limit に達すると、Postfix smtpd(8) サーバは "エラー数" 秒と $smtpd_error_sleep_time 秒の長い方の時間だけすべての応答を遅らせます。
エラーカウントが $smtpd_hard_error_limit (デフォルト: 20) に達すると、Postfix smtpd(8) サーバは接続を切ります。
注意: この機能はPostfixバージョン 2.1 には含まれていません。
Postfix smtpd(8) サーバは同じSMTP クライアントからの同時接続数と、あるクライアントが単位時間内に接続できる 接続数を制限することができます。これらの統計情報は anvil(8) サーバに よって管理されます (翻訳: anvil(8) サーバが止まると 接続制限は働かなくなります)。
重要: これらの制限はひどい乱用から smtpd(8) サーバを保護することを意図しています。これらを通常の正常なトラフィックの 制限には使わないでください: そうしてしまうとメールがおぞましい遅延に 苦しめらることになります。
1つのSMTPクライアントは最大 $smtpd_client_connection_count_limit の接続を同時に張ることができます (デフォルト: 50)。これはデフォルトの プロセス制限の半分です。
1つのSMTPクライアントは単位時間あたり最大 $smtpd_client_message_rate_limit 個のメッセージ配送要求を出せます (デフォルト: 制限なし)。
1つのSMTPクライアントは単位時間あたり最大 $smtpd_client_recipient_rate_limit 個の受信者アドレスに送れます (デフォルト: 制限なし)。
1つのSMTPクライアントは単位時間あたり最大 $smtpd_client_connection_rate_limit の接続を張ることができます (デフォルト: 制限なし)。
これらの制限は $smtpd_client_event_limit_exceptions で指定されたSMTPクライアントには適用されません (デフォルト: $mynetworks のクライアントは 接続を無制限に張れます)。
anvil_rate_time_unit パラメータにはクライアントの接続速度が測定される時間単位を指定します (デフォルト: 60s)。
QSHAPE_README ドキュメントの maildrop キューや incoming キュー active キュー、 deferred キューの議論を 読んで理解してください。
配送が遅い場合には、QSHAPE_README ドキュメントに書かれている qshape ツールを走らせてください。
受信者が少ないメッセージを投函するのではなく、メッセージごとに 複数の受信者を持つメールを投函してください。
/usr/sbin/sendmail の代わりにSMTPでメールを投函してください。 smtpd_recipient_limit パラメータ設定を調整する必要があるかもしれません。
メールの投函でディスクを食いつぶさないでください。同時投函数を チューニングしたり Postfix in_flow_delay パラメータ 設定をチューニングして、メールの投函速度を最適化してください。
DNS 検索による速度の低下を抑えるため、ローカルにネームサーバを 走らせてください。複数のPostfixシステムを動かす場合、上流ネットワークに 検索するアクセス数を増やさないようにするために、それぞれのローカル ネームサーバを共有した転送サーバに向けてください。
smtp_connect_timeout や smtp_helo_timeout 値を 減らして Postfixが応答しないリモートSMTPサーバに対する接続時間を長時間 無駄にしないようにします。
問題が多い配送先に対して、タイムアウトを減らし並列数を調整した 専用のメール配送 transport を使ってください。以下の "同時配送数のチューニング" を参照してください。
最初の試行で配送できないメールに対して fallback_relay ホストを使って ください。この "墓場" マシンは到達が難しい配送先への再試行時間を短く するのに使えます。以下の "遅延メール配送を試行する 頻度のチューニング" を参照してください。
永続的ライトキャッシュを大きく (64MB) して、ディスクの更新を 高速化します。これによりシステムクラッシュ時にファイルシステムの完全性を 妥協せずに、アクセススピードを最適化するようディスク更新を並び替えることが できます。
ソリッドステートディスク (永続的 RAM ディスク) を使います。 これはSMTPタイムアウトを短くしたり、問題のある配送先宛のメールを 配送する fallback_relay "墓場" マシンを組み合わせて使う、高価なソリューションです。
Postfixは同時に 1000 ものSMTPクライアントプロセスを動かすように 設定することができますが、同じリモートシステムに同時に 1000 の接続を 張ることはあまり望ましいことではありません。こういった理由で、Postfix にはこのいわゆる "大群" 問題を避ける機構があります。
Postfixキューマネージャは TCP スロースタートフロー制御戦略と同様な ものを実装しています: あるサイトに配送する際、始めは少数のメッセージを 送り、そしてうまくいっている間は並列数を増やしていきます; 混雑してきたら 並列数を減らします。
initial_destination_concurrency パラメータ (デフォルト: 5) は配送並列数を適用する前に、同じ配送先に送る メッセージ数の初期値を制御します。もちろんこの設定は、プロセス制限と、 特定のメール transport チャネルに対する配送先並列数制限を超えない範囲で のみ有効です。
default_destination_concurrency_limit パラメータ (デフォルト: 20) は同じ配送先に同時に送ることができるメッセージ 数を制限します。master.cf エントリの名前に "_destination_concurrency_limit" を付けたパラメータを使うと、特定のメッセージ配送 transport に対してこの 設定を上書きできます。
transport 特有の並列数制限の例:
local_destination_concurrency_limit パラメータ (デフォルト:2 ) は同じローカル受信者に対して同時に配送する メッセージ数を制御します。同じメールボックスに対する配送は逐次的で なければならず、大量の並列処理は実用的ではないため、低い制限を推奨します。 同じ受信者に対する並列配送を制限するのがよい、もう一つの理由: 受信者の .forward ファイルに負荷の高いシェルコマンドがあったり、その受信者が メーリングリストマネージャであると、これらのプロセスのインスタンスを 同時に過剰に動かしたくないでしょう。
20 という smtp_destination_concurrency_limit のデフォルトでもシステムを打ちのめすことなく著しい負荷を与えると思われます。 これをもっと大きな値に変える場合には注意してください。
上の並列制限のデフォルト値は広範囲な場面でうまく動きます。混雑したからと いって条件反射的にこれらのパラメータを変更すると、実際には問題を悪化させる ことになりかねません。特に、配送先への並列数のデフォルトを大きくすべきでは ありません。少数の大規模なドメインにメールを配送する transport のみに 限定すべきです。
並列数を大きくすることが要求される一般的な場面は、インターネットと イントラネットメール環境の間で大量のメールを中継するゲートウェイ上です。 およそ半分のメール (内行きと外行きが同じ量と想定します) が内部のメール ハブ宛です。内部メールハブは外部メールをすべてゲートウェイからのみ受け取る ため、ゲートウェイの内部SMTPサーバの容量に対する要求を大きくするように 設定するのは妥当です。
内行きの並列制限のチューニングには試行錯誤は不要です。特にゲートウェイが 複数の MX ホストに対して転送しているのであれば、大量に受け入れられる メールハブは簡単に (デフォルトの 20 より大きな) 50 や 100 の同時接続を 扱えるはずです。MX ホストがすべて動いていてタイムリーな方法で接続を受けて いるのであれば、スループットは高いでしょう。どの MX ホストも落ちていて 完全に応答しなければ、N 個の MX ホストがあると、接続レイテンシの平均は 少なくとも 1/N * $smtp_connection_timeout まで上がります。これは スループットを最大で配送先並列数 * N / $smtp_connection_timeout に制限 します。
例えば配送先並列数を 100 で2つの MX ホストがあるとすると、それぞれの ホストは最大 50 の同時接続が扱えます。一方の MX ホストがダウンし、 デフォルトのSMTP接続タイムアウトが 30s だと、スループット制限は1秒あたり 100 * 2 / 30 ~= 6 メッセージとなります。これは接続状況がよくて複数の MX ホストがある大量の配送先では接続タイムアウトを低く 5s くらいの値、もしくは すべてではない1つ以上の MX ホストがダウンした際の輻輳を防ぐのに 1s に してもよい、ということを示唆しています。
必要ならば、relay transport や特定の大容量な配送先専用の transport に 対して transport_destination_concurrency_limit に (これはキューマネージャの パラメータなので main.cf に) 高い値を設定し、smtp_connection_timeout に (このパラメータは transport ごとの名前ではないので master.cf で "-o" を 付けて上書きして) 低い値を設定してください。
default_destination_recipient_limit パラメータ (デフォルト: 50) はPostfix配送エージェントがそれぞれのEメールの コピーで送る受信者数を制御します。特定のPostfix配送エージェントに対して この設定を上書きすることができます。例えば "uucp_destination_recipient_limit = 100" とすると、それぞれの UUCP 配送ごとの受信者数を100に制限します。
Eメールメッセージがある配送先に対する受信者制限を超えると、Postfix キューマネージャは受信者リストを小さいリストに分割します。Postfixは メッセージの複数のコピーを並列に送ろうとします。
重要: メッセージ配送ごとの受信者数を増やす際には注意してください; smtpd(8) がメモリを使い果たしたりハード受信者 制限に到達すると接続を強制的に切ることがあり、そのメッセージが配送 されなくなってしまいます。
smtpd_recipient_limit smtpd_recipient_limit パラメータ (デフォルト: 1000) は Postfix smtpd(8) サーバが配送ごとに受け取る受信者数を 制御します。デフォルトの制限はSMTPクライアントが送る妥当なものよりも 大きい値です。この制限は暴走したクライアントからローカルメールシステムを 保護するために存在しています。
Postfix配送エージェント (smtp(8), local(8) など) がメッセージを配送できない場合、 メッセージ自身を非難するか、受信組織を非難するかもしれません。
配送エージェントがメッセージを非難する場合、キューマネージャは キューファイルに未来のタイムスタンプを与えてしばらく見られないようにします。 デフォルトでは、冷却期間はメッセージが到達してから経過した時間の長さです。 これはいわゆる指数的に遅らせるふるまいになります。
配送エージェントが受信組織 (例えばローカル受信ユーザやリモート ホスト) を非難する場合、キューマネージャはキューファイルのタイムスタンプを 進めるだけでなく、受信組織を "死亡" リストに置いてしばらくの間飛ばされる ようにします。
この処理は少数のパラメータ群で支配されます。
- queue_run_delay (デフォルト: 1000 秒)
- キューマネージャが遅延メールのキューをスキャンする頻度。
- minimal_backoff_time (デフォルト: 1000 秒)
- メッセージを見ない最短時間、および "死亡" 配送先から離れる最短時間。
- maximal_backoff_time (デフォルト: 4000 秒)
- 配送の失敗後メッセージを見ない最長時間。
- maximal_queue_lifetime (デフォルト: 5 日)
- 配送できないとして送り返されるまでにメッセージがキューに滞在する時間。 0を指定すると、最初の配送試行に失敗したらすぐにメールは送り返されます。
- bounce_queue_lifetime (デフォルト: 5 日, Postfixバージョン 2.1 以降で使えます)
- 配送できないと見なされるまでに MAILER-DAEMON メッセージがキューに とどまる時間。0 を指定するとメールは1回だけ試行されます。
- qmgr_message_recipient_limit (デフォルト: 20000)
- 多くのメモリ内キューマネージャデータ構造のサイズ。特にこのパラメータは "死亡" 配送先の短期間メモリ内リストを制限します。リストに合わない配送先は 追加されません。
重要: 遅延メール配送の試行頻度を上げたり、遅延メールキューを頻繁に flush すると、実際にPostfixメール配送のパフォーマンスが悪くなったと 感じるかもしれません。以下のような兆候です:
active キューが いっぱいになります。新しいメールは古いメッセージが遅延されないと active キューには入れません。 これはたいてい1つ以上のSMTP接続がタイムアウトする必要があるので、 時間がかかる処理です。
利用可能なPostfix配送エージェントがすべて配送できないサイト などに対する接続試行で占領されます。新しいメールは配送エージェントが 利用可能になるまで待たなければいけません。これはたいてい1つ以上のSMTP 接続がタイムアウトする必要があるので、時間がかかる処理です。
メールが頻繁に遅延する場合、配送試行の頻度を上げるよりも問題を修復する 方が常によいです。しかし配送試行の頻度しか制御できないのであれば、問題の ある配送先に対して専用の fallback_relay "墓場" マシンを使って、通常のメール配送のパフォーマンスを破綻させない ようにすることを検討してください。
default_process_limit 設定パラメータはPostfixが走らせるデーモンプロセスの数を直接制御します。 Postfix 2.0 の時点では、デフォルトの制限は 100 smtp クライアントプロセス、 100 サーバプロセスなどです。これはメモリが少ないシステムやバンド幅の 狭いネットワークのシステムを苦しめるかもしれません。
デフォルトではない default_process_limit を main.cf ファイルに指定することで全体のプロセス制限を変えることが できます。例えば、最大 10 の smtp クライアントプロセス、10 の smtp サーバ プロセスなどとするには:
/etc/postfix/main.cf: default_process_limit = 10
変更を有効にするには "postfix reload" を実行する必要があります。この 制限は main.cf が更新されても自動的には読み込まない Postfix master(8) デーモンによって強制されます。
特定のPostfixデーモンに対するプロセス制限は、master.cf ファイルを 編集することで上書きできます。例えば、同時に 100 のSMTPメッセージは 受けたくないが、ローカルメール配送のプロセス制限は変更したくない場合、 次のように指定できます:
/etc/postfix/master.cf: # ==================================================================== # service type private unpriv chroot wakeup maxproc command + args # (yes) (yes) (yes) (never) (100) # ==================================================================== . . . smtp inet n - - - 10 smtpd . . .
Postfixが過剰にファイルやソケットをオープンすると、プロセスは致命的 エラーで異常終了し、システムは "file table full" エラーをログに記録するかも しれません。
上の "Postfixプロセス数のチューニング" に書かれたプロセス数を減らします。プロセスを少なくすると、オープンする 必要があるファイルやソケットも少なくなります。
ファイルやソケットをもっと開けるようにカーネルを設定します。 詳細は極めてシステム依存であり、オペレーションシステムのバージョンで 変わります。以下の情報は必ずシステムチューニングガイドで検証して ください:
FreeBSD kernel パラメータには /boot/loader.conf で指定できるものや、 sysctl コマンドで変更できるものがあります。変更できるものはバージョンに よって変わります。
kern.ipc.maxsockets="5000" kern.ipc.nmbclusters="65536" kern.maxproc="2048" kern.maxfiles="16384" kern.maxfilesperproc="16384"
Linux kernel パラメータは /etc/sysctl.conf で指定でき、また sysctl コマンドでも変更できます:
fs.file-max=16384 kernel.threads-max=2048
Solaris kernel パラメータは Solaris FAQの "どうすればプロセス毎のファイル・ディスクリプタ数を増やせますか? (How can I increase the number of file descriptors per process?)" という エントリに書かれているように、/etc/system で指定できます。
* set hard limit on file descriptors set rlim_fd_max = 4096 * set soft limit on file descriptors set rlim_fd_cur = 1024