Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

ØMQの何がすごいのか理解してみる。導入編


橋本です。

これから数回にわたってØMQについて取り上げていこうと思います。

書いている中の人の趣味趣向により「どう使いこなすか?」というより「どう作られているか?」に軸足を移した
内容になると思います。
私と同じく「Stormってどういう作りになっているんだろう?」とか「Hadoopのソース読んでたら1日終わってた!」という人向けの内容になります。
その分ある程度深くもぐろうと思いますので、よろしくお願いします。

ØMQの紹介

ØMQというのは簡単に言うと「並列処理でパフォーマンスを出すための通信フレームワーク」です。
2007年ごろから開発されているOSSとしては歴史あるソフトウェアなのですが、
Stormの通信レイヤの実装で一躍有名になったのではないでしょうか?
少なくとも私はStormソースコード公開で初めて知り、作り手の熱い思いにわくわくしたクチです。

"MQ"という文字が含まれているので、ActiveMQ, RabbitMQ, KrestelなどのMessage Queueingソフトウエアと比較されることが多いようですが、
「通信フレームワーク」もしくは「うまくラッピングした通信ライブラリ」と考えたほうが提供している機能を正確に表していると思います。
他の製品のように「これを実行すればすぐに動き出しますよ」というレベルの提供ではなく、
「高性能に動いてカスタマイズしやすい部品を提供しているので、部品の意味を理解して好きに組み合わせてね」という感じです。

こういう性格の製品だからこそ、Stormでは利用しやすくかったのかもしれませんね。

様々な言語, OSで動く通信ライブラリ

ØMQ自体はC++で記述されていて、標準ではC言語APIが公開されています。
すでにコミュニティが30種以上の言語用のライブラリを提供しているので、普通の人が触る言語であればほぼ網羅していると思っていいでしょう。
更にプラットフォームについても一般的なOSや環境をほぼ網羅しています。
ためしに少しCygwin環境で試してみましたが、特に問題なく動いてしまいました。

以上から「さまざまな言語間・プラットフォーム間で動く、共通のネットワーク通信機能として使う。」ということもできるようになっています。
この後書きますが、ちょっと開発者側の意図からずれている使い方なので、安易に使うと痛い目を見ますが・・・。

商用サポートもできるライセンス

ライセンスはLGPLで公開されていますが、商用サポートも開発元のiMatrixから提供されています。
C/C++以外のバインディングを利用する場合には、あまり神経質にならないで利用できると思います。

最近の開発状況

2007年からの歴史あるプロダクトということもあり使っていて安心感があります。
ここ2,3年では新機能の追加もある程度落ち着いているという印象です。
最近の目立った新機能は2011年に追加された、PubSubでのFilterのPublisher側での実現なので非常に安定していると言えます。

今は、他のMQ製品が提供している機能のうちパフォーマンス的に有利なものの取り込みはほぼ終わり製品としての質を上げている段階のようです。
通信ライブラリは想定外の事象が起きやすいので、長く、沢山使われていて、安定しているというのは非常に心強いです。

ただAPIは結構変わってます。去年一年でも関数名が微妙に変わってびっくりしたことがあります。
ここら辺はNEWSを見て確認が必要です。

ØMQの思想みたいなもの

ØMQですがドキュメントやOreillyの書籍(まだEarly Accessですが)を読むと開発者が強烈な思想で作っていることがわかります。
意図的にスイートスポットを狭くした一点突破型のライブラリといって良いでしょう。
このため単なる通信ライブラリとして使おうとすると、「かゆいところに手が届かない、いまいちライブラリ」と見えなくもありません。

「使ってみてがっかり・・・」なんてことにならないように、ØMQの思想みたいなものを列挙してみます。

  1. ロックはしない、させない
  2. 車輪の再発明は嫌だ!
  3. リッチな機能より低レイヤでの完成度・パフォーマンス

とは言っても、私がドキュメントを読んだり、触ってみたりした経験をまとめたものなので、実際とは異なる部分があるかもしれません。
正確には公式のドキュメントを見てみてください

1.ロックはしない、させない

並列処理を実装する際に避けて通れないのが同期問題です。
複数コア、複数サーバにおいて並列で処理を実施する際に、データの矛盾を発生させないために、待ち合わせ処理としてロック処理の実装が必要になります。
スレッドでsynchronizedブロック書いたり、複数サーバに依頼した処理の完了をフラグで管理したり、並列処理の実装では多様される手法です。

ØMQはとにかくこのロックを嫌います。
「ロックなんて使ったら、ロックした点が単一障害点になって堅牢性が下がるし、何よりスケールアウトのボトルネックになる!」
と極力ロック処理の実装をしないで済む実装にこだわります。

このこだわりは、ØMQ自体が「manyコア、大量サーバでの並列処理において容易にスケールアウトする」という目的を追求しているためです。
「ロックしないと実現できないから提供されていないのでは?」とロックを避けるために機能を制限している思われるほど徹底しています。

このおかげで並列処理に対してすごく強いのですが、「あれ?これないの?」と肩透かしを食うような機能の偏りがあったりします。

2.車輪の再発明は嫌だ!

ØMQは汎用性を重要視しています。
今まで並列処理・分散処理を実現したソフトウェアでは、それ専用の並列処理実装が毎回作られ、そしてバグの温床になりがちです。
作っていても使っていても偉く苦労させられます。
ØMQ関連の資料では時々Apache ZooKeeperが比較多少になりますが、
並列処理の実現のために、複雑で、メンテナンス性の低く、再利用しにくい実装がZooKeeperで提供されていることを問題視しています。

このためØMQは再利用できること、さまざまな場所で使われることを重視しています。
多くのプログラミング言語、プラットフォームに対応しているのも、このせいでしょうね。

ただし、この考え方も「並列処理・分散処理において必要となる機能を提供する」というのが目的になります。
このため「何にでも使える」という意味での汎用性ではなく、
「並列処理・分散処理で実装が難しい部分を誰でも簡単に使えるようにした」という意味が強くなります。

3.リッチな機能より低レイヤでの完成度・パフォーマンス

特化した目的を持ったソフトウエアのため、提供する機能は思いの他限られています。
使い始めて最初に困ってしまうのは、次の2点ではないでしょうか?

  1. リアライザを持っていない
  2. 再送処理がない

他のMQ製品を知っている方にはびっくりする方もいると思います。
どちらもØMQを使う側が自前で用意する必要が出てきます。
ØMQを使っているStormでも再送処理は自前でかなり力を入れた実装しています。

どうやらØMQはアプリケーションの目的によって実現方法が大きく変わってしまうような機能については、提供する気がないようです。

それより低レイヤ・パフォーマンスを追及することに力を入れているため、提供される機能は自然と偏ったものになっています。
その代わりどこでも使えて高性能なPubSubがお手軽に使えたりするわけです。さすが一点突破型。

まあ、本格的に使い始めようとすると意外なものがなかったりするので、事前に調査しないと痛い目を見るかもしれません。

次回予告

ざっとØMQの思想というか癖のようなものを紹介してみました。
ちょっと熱く語りすぎてしまったので、偏った部分があったかもしれません。

次回は実際にサンプルコードを眺めながら、「この思想がどう提供されている機能に影響を与えているのか?」という点を紹介しようと思います。
実装に入るので、文章ばっかりの回は今回だけです。安心してください。

ご期待ください。それでは!