ØMQを復習

  • この名前よく聞くがよく理解もしていない
  • ChangeLogを見ると2013年にやっていたらしい。例によって。
  • jupyter notebook でも使われているらしい

というわけでちゃんと理解しなおしてみようといつものごとくsafaribooksを立ち上げて見た。
使う本はこちら
https://www.safaribooksonline.com/library/view/zeromq/9781782161042/

スタート

we are living in a connected world だそうな。low-levelでは面倒だが、high-levelではスピードが得られにくい。ちょうど中間が欲しい。そればzmqなのさ、という話。savior (救世主)
とか書いてある。ケンシロウめ。

メッセージキューの話

FIFO queue のこと。priority queue てなんだっけ。あれか、レジカウンターでは時間かかる人を後回しにしたほうが平均待ち時間がってやつ。
キューは大規模な分散システムを実現するためのキーファクターだって書いてある。さらに非同期通信(AIO)。リアルタイムでは必須。シングルスレッド上に複数のタスクをマップできる。JavaScriptっぽい。
よくある例としてWebappの話が次に続く。多量のアクセスに対して、シングルスレッドでは捌き切れず、マルチスレッドではDDoSされるとスレッド爆発してしまう。メッセージキューによるAIOならば(キューマシンを分ければ)これらの問題とともに対故障性にもすぐれるとか。

んでZeroMQ

このメッセージキューを実現する仕組みZeroMQ.sockets on steroids.
分散/平行アプリケーションのためのメッセージングライブラリ.

  • 単純さ
  • 性能
  • Brokerlessデザイン

中央集権でないらしい。(という事は対故障生の話は嘘なんでは…)

というわけで 僕らの友達  HelloWorld

サーバ側:
zmqでは全てはコンテキストから生成されるので、まずはこれを作ってソケットを生成する。
まずは準備して、

#include <zmq.h>

int main(int arc, char const *argv[])
{
  void* context = zmq_ctx_new();
  void* respond = zmq_socket(context, ZMQ_REP);

ソケットにアドレスをバインドして、

  zmq_bind(respond, "tcp://*:4040");       printf("Starting waiting...\n");

メッセージループに。

    for (;;) {
        wait_for_hello(respond);
        printf("Received: hello\n");
        sleep(1);
        send_world(respond);
        printf("send: world\n");
    }

終わったら(終わらないけど)後始末。

  zmq_close(respond);
  zmq_ctx_destroy(context);

  return 0;
}

んで肝心の受信の方はこんな感じになる(ちゃんと"hello"か確認してないだろう、というツッコミはちと置いておいて)

void wait_for_hello(void* respond)
{
    zmq_msg_t request;

    zmq_msg_init(&request);
    zmq_msg_recv(&request, respond, 0);
    zmq_msg_close(&request);
}

単純にメッセージを作って、ソケットからrecvするだけ。んで終わったらメッセージは捨てる。
んで送信。

void send_world(void* respond)
{
    zmq_msg_t reply;

    zmq_msg_init_size(&reply, strlen("world"));
    memcpy(zmq_msg_data(&reply), "world", 5);
    zmq_msg_send(&reply, respond, 0);
    zmq_msg_close(&reply);
}

同じように、基本的にメッセージを作ってソケットに投げつけるイメージ。メンバ変数というかメッセージのバッファを指定してmemcpyすんのがちとめんどいがそれはCだから
基本こんだけ。
https://github.com/tkuro11/zmqtutorial

まとめ

zmqはソケットを直に使うよりは相当に楽に非同期メッセージキューを実現するライブラリで、基本的に高レベルな操作を使ってかけるが、考え方はこれまでのモデルと大差ないので覚えやすい。ソケットの種類がすごいいっぱいあるけど、これはマルチキャストとかの対Nに対応しているから、といったところかなー。まだぼんやりしている。

次回はその機能てんこ盛りなソケットタイプから request reply の仕組みあたりかな。