NewtMQ(v0.2) と RPC over MQ

 こんにちは、インフラ統括本部の大山 裕泰です。
 NewtMQ v0.2 をリリースしました。

https://github.com/newtmq/newtmq-server/releases/tag/v0.2.0

 v0.2 では temp-queue を実装し Brokered MQ を利用した高速な RPC 処理が実現できるようになりました。
 今回は RabbitMQ(AMQP) 及び RabbitMQ(STOMP) に加えて Broker-less MQ の ZeroMQ、Google 謹製の RPC フレームワーク gRPC、そして NewtMQ で RPC のベンチマークを取ってみました。
 尚、御馴染みの Apache Kafka には 同様の機能がない模様 なため、検証しておりません。

temp-queue とは?

 NewtMQ (v0.2) に実装した temp-queue の仕組みは、以前のツチノコブログエントリ で紹介した rabbitmq-stomp プラグインのものと同じ仕組みになります。RabbitMQ 本体にも 同様の機能 が実装されています。
 簡単に説明すると pub-sub モデルにおいては Publisher と Subscriber はそれぞれお互いの存在を認知しませんが、Subscriber が、受け取ったメッセージを送ったある Publisher に対してメッセージを返信したいケースにおいて、当該 Publisher 専用の一時キューに対してメッセージを送ることで Subscriber と特定 Publisher 間でメッセージパッシングを行えるようにする仕組みになります。

 MQ を介して RPC を行う際、この仕組みが有効に作用します。

RPC over MQ

 RPC はネットワークを介した計算機資源を活用する分散システムの世界で 30 年以上の歴史がある枯れた技術です。
 分散システムにおいてはネットワークや計算機に障害が発生した際においてもサービスが安定して稼働できること、そして計算機資源の動的な増減に対応できることが古くからの課題として知られています。これらの問題を解決する手段の一つとして MessageQueue が広く利用されてきました。
 大規模化・複雑化した今日のシステムの多くはこうした仕組みに支えられています。数千 ~ 数万のサーバから構成される OpenStack では、RabbitMQ を用いた RPC を行うアーキテクチャ を採っています。

Broker-less MQ

 ここで、今回の比較する ZeroMQ に代表される Broker-less MQ と呼ばれる MQ について紹介します。
 ’MQ’ という名前を冠している点で RabbitMQ や NewtMQ と同じく、Queuing や Pub/Sub といったシステムモデルの実装をサポートする機能を提供している点で共通ですが、メッセージを仲介する ‘Broker’ を持たない点で異なります。
 RabbitMQ や NewtMQ の場合、以下のように Pub/Sub モデルにおいてクライアント (Publisher 及び Subscriber) は Broker に対してメッセージの送信/取得を行います。Apache Kafka や MQTT の実装として知られる ActiveMQ Apollo もこちらに分類されます。
   

 対して ZeroMQ の場合、以下のように Publisher が直接 Subscriber プロセスに対してメッセージを送信します。

 Broker を持た無い MQ システムでは、Broker を介した MQ と比較していくつかのメリットがあります。まずクライアントと Broker 間の通信が無くなるため、通信に伴うトラフィック量を減らせる事ができます。また ‘Broker’ で行う処理を省くため高速なメッセージパッシングを行うことができます。

ZeroMQ

 ZeroMQ の用途は Queuing や Pub/Sub モデルの実装に止まりません。ここで ZeroMQ 自体について補足で紹介します。
 ZeroMQ では ‘ZeroMQ Socket’ と呼ばれる TCP Scoket を抽象化したオブジェクトに対して、1対1, 1対N, N対1, N対N の通信を実現する機能 を加えています。更に、これらの通信のベースに Queuing の仕組みを設ける事で通信の可用性を高め、従来の TCP Socket を用いた通信を行うアプリケーションに対して、高い機能性と可用性を備えた仕組みを提供しています。
 更に ZeroMQ の Router Socket を利用することで、メッセージの配送を仲介する Proxy をつくることができ Broker MQ のような振る舞いをさせることも出来ます。

測ってみた

 それではここで MQ を利用した RPC 処理のベンチマークを取ってみます。ベンチーマークは Broker MQ の雄 RabbitMQ(AMQP, STOMP) Broker-less MQ の代表格 ZeroMQ、そして RPC フレームワークとして現在非常に活発に開発が行われている Google 謹製の RPC フレームワーク gRPC、そして NewtMQ に対して行います。ベンチマークでは以下の RPC ベンチマークツールを利用します。

* https://github.com/userlocalhost2000/rpc-bench

 各クライアントライブラリはそれぞれ以下を使用しています。

ターゲット ライブラリ (バージョン)
RabbitMQ(AMQP) bunny (2.3.1)
RabbitMQ(STOMP) stomp (1.4.0)
NewtMQ stomp (1.4.0)
gRPC grpc (0.14.1)
grpc-tools (0.14.1)
ZeroMQ libzmq (4.2.0)
ffi-rzmq (2.0.4)
ffi-rzmq-core (1.0.5)

 今回は、各手法の実行時間の比較が目的のため、クライアント、サーバ、及び MQ を全て同一ホスト上で実行しています。実行ホスト環境は以下のとおりです。

CPU Intel Core i7-6700 CPU @ 3.40GHz
RAM 32GB
OS Ubuntu14.04
Ruby 2.2.2
RabbitMQ 3.6.1-1

 RPCBench では、クライアントがサーバに対して数値を送り、サーバが送られた数値に 1 を足して結果を返し、最終的にすべての結果が送った数値 + 1 になっているかを検査するまでに要した時間を、リクエスト数、同時実行数のパラメータを変えて取得できます。
 
 まず同時実行数を 1 に固定し、リクエスト数を 32k ~ 512k にそれぞれ設定した結果を以下に示します。

 予想通り ZeroMQ が最も早いですが NewtMQ もほぼ同じ程度の速度で RPC をさばけています。予想以上のスピードに我ながら驚いています(結果の取り違いを疑いました)。
 それぞれのベンチマークにおいて RPC サーバ処理 (数値を受け取って +1 する処理) は共通ですが、クライアントライブラリがそれぞれ異なるため、純粋に MQ の違いについての比較にはなりません。
 ただし RabbitMQ(STOMP) との比較に関しては、サーバ処理もクライアントライブラリもそれぞれ同じものを用いており、MQ だけが違うので純粋な NewtMQ と RabbitMQ(STOMP) の性能の違いがこの結果かわかります。

 続いてリクエスト数を 10k に固定し、同時実行数を 4 ~ 64 にそれぞれ設定した結果を以下に示します。

 

 やや ZeroMQ との差が開きましたが Broker MQ においては NewtMQ が最も速度が出ていることがわかります。

おわりに

 NewtMQ に temp-queue を実装したことで、RabbitMQ よりも高速に RPC を処理できることを確認しました。
 しかし NewtMQ はその他の機能面や信頼性、実績において RabbitMQ に遠く及ばないので、メジャーバージョンがリリースできるくらいまでは暖かい目で見守っていただければと思います。

 性能改善の余地はまだ残されているので、NewtMQ はまだまだ速くなると思っています。

ベンチマークだけではわからない

 

nandのflashなんですが、

過去、ベンチマークの結果載せてますが、

その中でhuaweiが圧倒的だという話をしてたと思います。

ベンチマークではhuaweiが強い。価格もhuaweiが強い

であれば、huawei一択じゃないかと思っていたのですが、

現在、3つのnand flash(fusion-io,virident,huawei)で本番運用しているうちにnandのflashカードの本来の力が見えてきました。

信頼性についてはまだ期間が足らなさすぎるのでここでは控えますが、

性能については差がでてきたと思います。これについて共有します。

基本的にはfusion-io,viridentの製品に性能の差は感じられませんでしたが、

huaweiのカードだけiowaitが増大する周期がありました。

vmstatで確認するとわかるのですが、定期的にIOWAITの数値が増大し、HTTPレスポンスが0.001秒だったものが1秒以上となり不安定な状況が見られる。
その他のサーバはIOWAITの数値は増大しておらず、HTTPレスポンスも0.001秒で安定しています。

ということで、現時点(2014年7月)での結論

ベンチマークではhuaweiが圧倒的だが
※ベンチに特化したチューニングがされてるとか?

安定した製品を選ぶならfusion-ioがお勧め。fusion-ioよりも価格が安ければviridentもあり。

huaweiは圧倒的に安い場合で、かつ、ある程度の不安定な状況でも許容できるサービスで利用するのが良いのではないかと思います。

DB系はfusion-io,virident

コンテンツ配信系はhuawei

といった感じですかね。

fusion-ioのIRQ割り当ても従来のiodrive2製品に比べて増やされているので、マルチコアな環境では、かなり安定した製品になったんじゃないかと思います。

下記はhuaweiの製品が乗っているサーバのvmwstat結果です。
時々IOWAITがでてパフォーマンスが劣化します。

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
 4  1      0 413892 3361696 111236464    0    0 13500  8008 398584 46838  3 17 80  0  0
 3  0      0 395788 3361720 111254912    0    0 15328   456 397737 48659  3 17 80  0  0
 5  0      0 379544 3361748 111272928    0    0 14236   152 403618 49095  3 18 79  0  0
 0 20      0 414668 3361732 111235128    0    0  5792 61248 333090 81848  1 10 55 34  0
 4  0      0 399084 3361784 111255688    0    0 18884   484 411634 70012  4 22 66  8  0
 3  0      0 382468 3361856 111272960    0    0 15092  7248 418057 52394  3 20 77  0  0

 

上記のblock waitの際のtop情報はこちらです。huaweiでは30秒から60秒の間でこのようなwaitが入ります。プチフリーズしてるんですかね?この時のHTTPレスポンスも確かに悪くなっている事を確認しています。

top - 18:06:37 up 5 days,  6:47,  2 users,  load average: 4.62, 2.57, 1.75
Tasks: 421 total,   1 running, 420 sleeping,   0 stopped,   0 zombie
Cpu0  :  0.0%us,  1.0%sy,  0.0%ni, 35.0%id, 62.0%wa,  0.0%hi,  2.0%si,  0.0%st
Cpu1  :  0.0%us,  0.0%sy,  0.0%ni, 99.0%id,  0.0%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu2  :  0.0%us,  1.0%sy,  0.0%ni, 63.0%id, 35.0%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu3  :  0.0%us,  0.0%sy,  0.0%ni, 97.1%id,  0.0%wa,  0.0%hi,  2.9%si,  0.0%st
Cpu4  :  0.0%us,  0.0%sy,  0.0%ni,  0.0%id, 98.0%wa,  0.0%hi,  2.0%si,  0.0%st
Cpu5  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu6  :  0.0%us,  0.0%sy,  0.0%ni,  0.0%id, 98.0%wa,  0.0%hi,  2.0%si,  0.0%st
Cpu7  :  0.0%us,  0.0%sy,  0.0%ni, 98.0%id,  0.0%wa,  0.0%hi,  2.0%si,  0.0%st
Cpu8  :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu9  :  0.0%us,  0.0%sy,  0.0%ni,  0.0%id, 99.0%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu10 :  0.0%us,  0.0%sy,  0.0%ni,  0.0%id,100.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu11 :  0.0%us,  0.0%sy,  0.0%ni,  0.0%id,100.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu12 :  0.0%us,  1.0%sy,  0.0%ni,  0.0%id, 99.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu13 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu14 :  1.0%us,  0.0%sy,  0.0%ni,  0.0%id, 98.0%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu15 :  0.0%us,  0.0%sy,  0.0%ni,  0.0%id, 99.0%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu16 :  0.0%us,  0.0%sy,  0.0%ni, 99.0%id,  0.0%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu17 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu18 :  0.0%us,  0.0%sy,  0.0%ni,  0.0%id,100.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu19 :  0.0%us,  0.0%sy,  0.0%ni, 99.0%id,  0.0%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu20 :  0.0%us,  1.0%sy,  0.0%ni,  0.0%id, 99.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu21 :  0.0%us,  0.0%sy,  0.0%ni,  0.0%id, 99.0%wa,  0.0%hi,  1.0%si,  0.0%st
Cpu22 :  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Cpu23 :  0.0%us,  0.0%sy,  0.0%ni,  0.0%id, 99.0%wa,  0.0%hi,  1.0%si,  0.0%st

 

下記はテストしたサーバのトラフィックとロードアベレージの参考のグラフです。

iomemory 3200 (fusion-io)
iomem
※安定しています。

flash max 2 (virident)
virident
※こちらも安定しているように思います。スパイクしている部分がありますが、基本安定

es3000 (huawei)
huawei
※不安定とはまではいかないですが、ロードアベレージが定期的に高まる。何か裏で動いているんですかね。