ククログ

株式会社クリアコード > ククログ > milter managerのスケーラビリティ向上計画

milter managerのスケーラビリティ向上計画

milter managerの開発を始めたのが2008年の9月なので、2年と少し前になります。この当時はPostfixでmilterを使うというのはそれほど一般的ではありませんでした。しかし、最近ではPostfixでmilterを使うというのが選択肢の1つになっています。これは、Postfixのmilter対応が強化されたことと、Web上にPostfixでmilterを利用した事例が増えてきたことが大きな要因でしょう。

このような状況になると、より規模の大きなメールシステムでもmilter managerを利用することを想定しないといけません1。そのため、milter managerがよりスケールするように内部の構造を改良する予定です。これらの改良は近いうちにmilter manager 1.6.3としてリリースする予定です。1.6.Xシリーズの間は「実験的」な扱いで機能を提供し、1.8.0になった段階で「正式」な機能扱いとする予定です。

改良は以下の2点です。

  1. マルチプロセス対応

  2. イベントループの高速化

マルチプロセス対応ではマルチコアのマシンでの性能向上を目指します。イベントループの高速化では1プロセスあたりの性能向上を目指します。ちなみに、現在はシングルプロセス・シングルスレッドで、イベントループにはpoll(2)2を使っています。

マルチプロセス対応

マルチコアを活かすためにはマルチプロセス対応にするか、マルチスレッド対応にするかという選択肢がありますが、milter managerではマルチプロセスを採用します。これは、milter manager内部にあるRubyインタプリタとの相性からです。スレッド毎にRubyインタプリタを持てるのであればマルチスレッドでもよかったのですが、現在のRuby(MRI)はそれができないため処理を直列化する必要があり、マルチスレッドにしてもマルチコアを活かしきれないと判断しました。そのためマルチプロセスを選択しています。

以下のようにPostfixのmaster/smtpdと同じような構成になります。

シングルプロセス(現行):
 inet@10025
------------ milter manager

マルチプロセス(改良後):

 inet@10025                           +- milter manager (worker1)
------------ milter manager (master) -+- milter manager (worker2)
                                     ...
                                      +- milter manager (workerN)

Postfixのmasterが「milter manager (master)」に対応し、smtpdが「milter manager (worker)」に対応します。

milter manager (master)が外部からの接続(smtpdからの接続)を受け付け、実際の処理はmilter manager (worker)が行います。外部からの接続の受け付けは、常にmilter manager (master)が行うため、外からはシングルプロセスの構成と区別がつきません。つまり、外部(smtpd)からはmilter managerがどちらの構成を使っていても同じように扱えるため、Postfixの設定を変更する必要はありません。

マルチプロセス構成にするとmilter manager (worker)の数だけCPUコアを利用して並列に処理することができます。

イベントループの高速化

メールシステムは複数のメールを同時に扱います。milter managerはI/Oを多重化し、I/O待ちの間に別のメールを処理することにより、同時に複数のメールを処理しています。つまり、I/OとI/Oを待っている間の処理を繰り返して動作することになります。この繰り返しがイベントループです。ここを高速化することにより、1プロセスで同時に処理できるメール数を増やします。

規模の大きなメールシステムではより同時接続数が増えますが、このとき、I/Oを多重化する仕組みによって性能特性が変わってきます。伝統的なI/O多重化の仕組みはselect(2)やpoll(2)ですが、これらはI/O対象の数(監視するファイルディスクリプタ数)が増えると大きく性能が落ちることが知られています3。ちなみに、現在はmilter managerはpoll(2)を使っています。

milter managerは1つのメールに対して複数のmilterに接続するため、I/O対象の数がすぐに大きくなってしまいます。例えば、6つmilterを利用している場合は、1メールに対してI/O対象の数が6つ増えます。同時に30メールを処理する場合はI/O対象の数が180になるわけです。そのため、規模が大きいメールシステムではpoll(2)の性能劣化が顕著になるくらいまでI/O対象の数が増えてしまうことになります。

そこで、milter managerのイベントループでpoll(2)ではなくlibevを利用できるようにします。libevを利用することにより、I/O対象の数が増えてもイベントループでの急激な性能劣化を防ぐことができ、より大きな規模のメールシステムでもサービスを提供できるようになります。

まとめ

現在、より大きな規模のメールシステムでもmilter managerを利用できるようにするためにmilter managerを改良しています。まだ改良が終わっていないので少し気が早いのですが、どのような改良を進めているかを紹介しました。

どちらの機能も設定を1つ変更するだけで切り替えることができるようになるので、milter manager 1.6.3では簡単にここで紹介した改良を試すことができるようになる予定です。楽しみにしていてください。

最後になりましたが、今年もmilter managerをよろしくお願いします。

  1. これまでは中規模のメールシステム(アカウント数が1000件いかない程度)でも利用できることを想定していた。

  2. GLibのメインループのバックエンドがpoll(2)だから。

  3. 100以下ならそれほど変わらない