ページ

2011年1月13日

はじめてのZeroMQ その1

MQ関係は「遅い!機能過多!」というイメージがあって敬遠していました。最近、もう一度調べ直しています。その中でZeroMQと言う変なのがいるらしい、と言うことで、しばらくはZeroMQ関係のお話です。ざっとドキュメントを読んだ感想は、MQと言うより、ネットワークをもう少し抽象化して、ユニキャスト、ブロードキャストを簡易に使えるようにしている、と言うものです。そのため、APIもとても薄くローレベルなものです。僕はこれくらいのものが好きだったりします。
トップページには次のように特徴を書いています。


  • 並列フレームワークとして振る舞うソケットライブラリ
  • プロセス間, IPC, TCP, マルチキャストを横断的にメッセージ伝搬
  • fanout, pubsub, pipeline, request-replyによるN対N接続
  • クラスタ製品やスーパーコンピューティングとして使える十分なスピード
  • スケーラブルなマルチコアでメッセージ送受信アプリ用の非同期IO
  • コミュニティはでかくて活発だよ
  • C, C++, Java, .NET, Pythonなど20以上の言語バインディングあるよ
  • Linux, Windows, OS XなどたいていのOSで動くよ
  • LGPLだから商用利用無問題

と書いています。とっても速いし、ローベルなことは大体できるということでしょうか。そうそう、それから、MQ用の専用のサーバがいらないのもメリットの一つです。

サンプルコードを見ながら、いろいろ試してみます。全部は一度には大変なので、pubsub関係から。pubsubはpublisherが接続しているsubscriberに一斉にデータを配信するものです。
publisherのコードは次。言語はPythonですが、C/C++ライブラリのラッパーなので、どの言語でも大差ないでしょう。
import time
import zmq

def main(count):
    ctx = zmq.Context()
    sock = ctx.socket(zmq.PUB)
    sock.bind("tcp://*:5555")
    print "Waiting for clinets..."
    time.sleep(0.1)
    print "Starting broadcast..."
    for i in range(count):
        sock.send_pyobj("HELLO %d" % i)
    
    print "Wait for a while"
    time.sleep(1)
    print "Done"

if __name__ == "__main__":
    import sys

    main(int(sys.argv[1]))

最後のsleepは別スレッドでメッセージの送受信を行うので、それを待っているもの。
subscriber側は
import time
import zmq

def main(count):
    ctx = zmq.Context()
    sock = ctx.socket(zmq.SUB)
    sock.connect("tcp://localhost:5555")
    sock.setsockopt(zmq.SUBSCRIBE, "")
    print "recieving broadcast..."
    for i in range(count):
        val = sock.recv_pyobj()
        print val
    print "done"
        
if __name__ == "__main__":
    import sys

    main(int(sys.argv[1]))

zmq.SUBで作ったsocketオブジェクトにし対してsock.bindするとエラーで怒られました。Subscriberはpublisherに接続するしか生きる意味がないらしいです。

さて、これでpublisher側を起動してからsubscriberを起動するのが普通の流れですが、ZeroMQってsubscriberを起動してからpublisherを起動しても動作します。定期的にpublisherに接続を試みているようです。publisherのWait for clients...の後のtime.sleepの時間ですが、0.1秒だとsubscriberを先に起動しておいてもメッセージの送受信ができますが、0.01秒だと送受信できませんでした。publisherの存在チェックが0.1秒間隔ぐらいなんでしょうか?

多段階のルーティングはできないかやってみましたが、無理そうです。どうしてもやりたければ自分でルーティングしないといけません。

ノードの管理は自前でやらないといけないのは、ちょっと大変だな〜、という感じがします。

でわでわ

追記
======

これはよくまとまっているので、その2はなし。

0 件のコメント: