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プロセスあたりの性能向上を目指します。ちなみに、現在はシングルプロセス・シングルスレッドで、イベントループには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をよろしくお願いします。
Rubyのリファレンスマニュアルを高速に全文検索するるりまサーチを 第3回フクオカRuby大賞に応募したら本審査に呼んでもらえたので、2/3に福岡に行ってるりまサーチを紹介することにしました。
(おそらく、)一般の人は審査会場(?)には入れないので、ここで紹介して「興味があったら見にきてください」とは言えないのが残念です。(おそらく、)2/3は時間にたいへん余裕があるので、福岡の人たちと交流できると嬉しいですね。
先日、milter managerのスケーラビリティ向上計画を紹介しましたが、そこに書いた内容を実装したmilter manager 1.6.4をリリースしました。(メーリングリストでのアナウンス)
スケーラビリティ向上のための主な追加機能は以下の3点です。
このうち、「マルチプロセス対応」と「libev対応」は「実験的」な扱いということで、デフォルトでは無効になっています。「writeの非同期化」は有効になっています。このため、Postfixや子milterのreadが遅い場面では劇的にスループットが向上するでしょう*1。
また、スケーラビリティ向上に加えてRuby対応を強化しています。代表的な変更はRuby 1.9.2に対応したことです。Rubyでmilterを書くのがより便利になりますね。
milter manager 1.6.4をリリースしたので代表的な変更内容を紹介しました。
*1 例えば大量の宛先を削除するmilterを使っている場合。この場合、Postfixのcleanupのreadが遅い。
昔から「Rubyはドキュメントが弱い」と言われてきました。「PythonやPHPはあんなにドキュメントが揃っているのに、それに比べてRubyは。。。」というわけです。でも、待ってください。ドキュメントは記述が充実しているだけで十分ですか?簡単に目的のドキュメントにたどりつけますか?
GoogleやBingなどの検索エンジンや、Amazonを筆頭とするECサイトは「探しものを見つけやすくする」ことにどんどん磨きをかけています。なぜ、ドキュメントの検索機能はそれほど進歩しないのでしょうか?
ドキュメントの検索機能が、検索エンジンやECサイトでも使われているような最新の検索パターンを取り入れ、もっとリッチになればプログラミングがもっと楽しくなるはずです。それをRubyのドキュメントで実現しようとしているのがるりまサーチです。
最近、るりまサーチがよりパワーアップしたので、どう変わったかを紹介します。↓は、第3回フクオカRuby大賞用に作ったるりまサーチの資料です。
PythonのドキュメントページはSphinxで生成されています*1。SphinxにはJavaScriptで実装された検索機能がついていて、キーワードによる検索のみが可能です。シンプルで検索サーバーを用意しなくてもよい手軽さはうれしいですが、よいキーワードを思いつかないと目的のドキュメントにたどり着くのは難しいです。
PHPのドキュメントページの検索機能は検索対象のカテゴリ化とYahoo!の検索機能を利用しています。Yahoo!の検索機能を使った部分ではHTMLのページだけではなく、Atomフィードのファイルもヒットしてしまっています。通常のWebサイト検索ではAtomフィードもヒットしてよいかもしれませんが、ドキュメント検索ではAtomフィードはノイズです。既存の検索機能を利用することもできますが、より精度をよくしたい場合はチューニングが必要だということです。
プログラミング言語のドキュメント検索は通常のWeb検索や文書検索などの自然言語の検索と傾向が違います。例えば、記号が含まれていたり、省略語が使われていたり、メソッド名・クラス名などキーワード(スコアを上げた方がよい語)となる語がわかりやすかったりといった具合です。このあたりをふまえた上でチューニングするとより探しやすいドキュメント検索機能ができあがります。
では、チューニングした結果は、どのようにユーザーに見せるとよいでしょうか。それには先進的な検索機能を提供するWebサイトが参考になります。よい検索機能がデザインパターンとしてまとめられています。
検索と発見のためのデザイン ―エクスペリエンスの未来へ
オライリージャパン
¥ 4,563
昨年末、「検索と発見のためのデザイン」という本がオライリージャパンから出版されました*2。この本の中で、実際のWebサイトのスクリーンショットと一緒に、「検索のデザインパターン」としてよく使われるよい検索機能をパターン化しています*3。パターンの数は少ないのですが、このように検索機能をデザインパターンとしてまとめているのがよかったです。検索に興味のある方はこの部分だけでも眺めてみるとよいでしょう。
パワーアップしたるりまサーチにもこの本で作っている検索のデザインパターンにでてくる機能が実装されています。るりまサーチが、ドキュメント検索にチューニングした結果をどのように見せているかを2つ紹介します。
検索のデザインパターンの1つとして入力補完(オートコンプリート)機能が紹介されています。デスクトップでもWebでもかなり広まっているので見かける機会が多いのではないでしょうか。
Web検索の場合はクロールした文書の中によく含まれている単語や、ユーザが多く入力する単語などを元データとして、ユーザーの入力を補完することが多いでしょう。しかし、ドキュメント検索の場合、クラス名やメソッド名など、補完対象とすべきキーワードがわかりやすく含まれているので、それを使います。これにより、ノイズが少ない補完候補を出すことができます。
Yahoo!など外部の検索エンジンを使っている場合はこのようなチューニングは難しいのではないでしょうか。
ちなみに、るりまサーチの入力補完機能はgroonga本体に組み込まれている「サジェスト機能」を利用しています。groongaのサジェスト機能はまだ仕様が固まっていないため、APIが変更される可能性が大きくあります*4。使用する場合はそのことに注意してください。
なお、るりまサーチの入力補完のUI部分はjQuery UIのAutocompleteを利用しています。
groongaでは「ドリルダウン」と呼んでいる機能で、絞り込み候補を表示する機能です。るりまサーチでは「クラス名」や「ドキュメントの種類」(インスタンスメソッドのドキュメントや定数のドキュメントなど)など、いくつかのグループを作って、それぞれのグループ毎に絞り込み候補を表示しています。
この機能のよいところは、キーボードで入力しなくてもマウスクリックだけで絞り込んでいけることです。一昔前の検索では「よいキーワード」を自分で考えて絞り込んでいく必要がありましたが、この機能を使うことにより「提示されたキーワードから選ぶ」だけでよくなります。便利で探しやすくなりましたね。
プログラミング言語のドキュメント検索システムはもっと便利になって、プログラマを助けるべきという話でした。そのためにるりまサーチが提供している今風の検索機能を2つ紹介しました。どちらも、ユーザーが探したいものを見つけるためのキーワードを完全に知らなくても見つけることができるようにするための機能です。今後は、これらの機能のように、ユーザーがそれほど頑張らなくても見つけたいものにたどりつける機能がより一般的になってくることでしょう。
みなさんもWebサイトに検索機能をつけるときは、テキスト入力フォームを1つ置くだけではなく、さらに別の方法も加えてより簡単に目的のものを見つけやすくできないかを考えてみてください。
*1 Sphinxはgroongaのドキュメントでも使っていますね。
*2 翻訳本です。
*3 著者は建設業界やXP界隈でもよく名前のでるアレグザンダーに大きく影響を受けているようです。
*4 なのでまだドキュメント化されていない。