第1回 Cloud Foundry 輪読会




NATSを んだ。
NATSを読んだ。

   Katsunori Kawaguchi
        @hamakn
       2011-10-18
Cloud Foundryのmessagingに
利用されている、『NATS』の
    コードを読んだので、
       そのまとめを、
       デモを交えつつ
   共有したいと思います。
アジェンダ
1. コードリーディングの下準備、NATSとは?

2. NATSのコードリーディング

3. Cloud FoundryでのNATS(ちょっとだけ)

4. NATS cluster
自己紹介
• 川口 克則 @hamakn
• NTTコム所属
• Web/スマートフォンアプリの開発
  主にRails

• 社内PaaSの第一候補として
  Cloud Foundryを検証中(2011年10月~)
コードリーディングの下準備
    NATSとは?
NATSとCloud Foundry



 この
実装が
NATS

           Cloud Foundry The building of the Open PaaS OSCON2011
              http://www.slideshare.net/derekcollison/oscon-2011
NATSとCloud Foundry(2)




   青い
  矢印が
 NATSの
メッセージ       Cloud Foundry The building of the Open PaaS OSCON2011
               http://www.slideshare.net/derekcollison/oscon-2011
NATS
  https://github.com/derekcollison/nats/

• A lightweight EventMachine based
  publish-subscribe messaging system.
• Rubyで実装
• 依存gem
  – eventmachine, json_pure, daemons, thin


• ver0.4.10ではsingle server design < SPOF
publish-subscribe messaging

                       受信側はtopicを
                        subscribe



送信側はメッセージを
  topicにpublish


 • topicを介して多対多で通信する
   メッセージングモデル
 • メリット:スケールさせやすい/疎結合にしやすい
EventMachine
       http://rubyeventmachine.com/

• Fast, simple event-processing library
  for Ruby programs.
• 非同期I/O処理を行えるライブラリ
• Reactor pattern
  – Rubyだと他にcool.io(旧rev)など
  – 他言語であればnode.js, AnyEvent, Twistedなど
• 利用例
  – thin(httpd), em-websocketなどなど
Reactor pattern
• シングルスレッドの
  イベントループで
  非同期I/Oを実現する
  デザインパターン
EventMachineのサンプル1
            エコーサーバ
require 'eventmachine'

module Echo
  def receive_data(data)
    send_data(data)
  end
end

EM.run do
  EM.start_server("0.0.0.0", 10000, Echo)
end

                                            デモ
EventMachineのサンプル2
          HTTPクライアント
require 'eventmachine'

hosts = [“www.google.co.jp”, “www.yahoo.co.jp”]
hosts_size = hosts.size
EM.run do
  hosts.each do |h|
    http = EM::Protocols::HttpClient.request(:host =>
  h, :port => 80, :request => “/”)
    http.callback do |response|
      p response[:status]
      EM.stop if (hosts_size -= 1) <= 0
    end
  end
end
                                                  デモ
ここまでのまとめ
1. Cloud FoundryはNATSを使っている
2. NATSはEventMachineを使ったPub/Sub
   メッセージングシステム
3. Pub/Subはメッセージングの一方式
4. EventMachineはReactorパターンによる
   非同期I/Oを行うためのライブラリ
5. EventMachineのサンプルを動かして
   なんとなく慣れた
NATSのコードリーディング
ファイル構成
• lib
  nats/client.rb              NATSクライアント
  nats/server.rb              NATSサーバの起動
  nats/server/server.rb       NATSサーバ本体
  nats/server/connection.rb   コネクションのメッセージ処理など
  nats/server/sublist.rb      Subscriberのリスト管理
  nats/server/options.rb      起動オプションのパース
  nats/ext/                   JrubyやRuby1.8.6へのパッチなど

•   bin                       サーバやクライアントの起動コマンド
•   spec                      テストコード
•   examples                  サンプルコード
•   benchmark                 ベンチーマークコード

• lib                         “cluster” branchのみ
  nats/server/cluster.rb      NATSサーバを束ねるクラスタ本体
  nats/server/route.rb        クラスタ構成時のルーティング
サンプルを動かす1
                             Sub
                         subject:foo


     Pub
                NATS         Sub
 subject:foo
                         subject:foo
message:hello   Server


                             Sub
                         subject:bar

デモ
サンプルを動かす2
                                     Sub
                                subject:foo.>
      Pub
subject:foo.bar
 message:hello
                       NATS          Sub
                                subject:foo.*
                       Server
        Pub
subject:foo.bar.hoge
   message:hello
                                    Sub
                                subject:foo

   デモ
サンプルを動かす3
               queue
                                    Sub
                                subject:foo


     Pub
                  NATS              Sub
 subject:foo
                                subject:foo
message:hello     Server


                  3つのうち             Sub
                どれか1つにpublish   subject:foo

デモ
NATSサーバの起動
    @ lib/nats/server.rb 25行目~
• 左:EMのechoサーバ                 • 右:NATSサーバの開始
require 'eventmachine'         EM.run do
                                 EM.start_server(
module Echo                        NATSD::Server.host,
  def receive_data(data)           NATSD::Server.port,
    send_data(data)                NATSD::Connection
  end                            )
end                            end

EM.run do
  EM.start_server("0.0.0.0",
   10000, Echo)
          Echo
end
メッセージの送信
• Subscribe
NATS.start
  NATS.subscribe(subject) {|msg, _, sub|
    puts “#{header} Receive on [#{sub}] : ‘#{msg}’”
  }
end
(@ bin/nats-sub 35行目)


• Publish
NATS.start
  NATS.publish(subject, msg) { NATS.stop }
end
(@ bin/nats-pub 23行目)
NATSのプロトコル
   “OP foo queue 2/r/n” 的メッセージが飛ぶ
                 OPが命令
• クライアント→サーバ                     • サーバ→クライアント
   –   PUB                          –   MSG
   –   SUB                          –   OK
   –   UNSUB                        –   ERR
   –   PING                         –   PING
   –   PONG                         –   PONG
   –   CONNECT                      –   INFO
   –   INFO                         –   UNKNOWN
   –   UNKNOWN
• lib/nats/server/connection.r   • lib/nats/client.rb 446行目~
  b 57行目~ に受信処理                    に受信処理
メッセージングの例
      サンプルを動かす1 の場合
Server            Sub            Pub
INFO         =>   *
*            <=   CONNECT
*            <=   SUB foo
INFO                        =>   *
*                           <=   CONNECT
*                           <=   PUB foo hello!
MSG hello!   =>   hello!
Sublistの管理
    @ lib/nats/server/sublist.rb
• subject “foo”, “bar”, “foo.*”, “foo.>”
  を実現する仕組み
Struct Subscriber
  :conn     NATSD::Connectionのインスタンス
struct SublistLevel
  :nodes    subject => SublistNodeのハッシュ
  :pwc      subject=“*”時のSublistNode
  :fwc      subject=“>”時のSublistNode
struct SublistNode
  :leaf_nodes      NATSD::Subscriber の配列
  :next_level      SublistLevel
NATSのテスト
• rspec
• rspec/spec_helper.rb
  – NatsServerControl超便利
NATSの問題点
• 現状single server
• “cluster” blanchが存在
• 設計方針
  Cluster Design Overview
  https://github.com/derekcollison/nats/
  wiki/Cluster-Design
なぜNATSなのか?
• 他の案
  –   AMQP(RabbitMQ)
  –   Storm
  –   RestMS
  –   XMPP
• RubyWorld Conf. / Why ruby?
  – Allows great productivity and rapid iteration
  – Language perfomance is not always key
Cloud FoundryでのNATS
   (ちょっとだけ)
NATS Server(NATSD)の起動
• @ bin/vcap
`#{nats_server} –p #{@uri.port} –P #{@pid_file} –d 2>
  /dev/null`


• 現状、全てのvcapサーバで
  nats serverが動作してしまう
  (本来 mbus:// で指定されるサーバ以外は不要)
青い
  矢印が
    NATSとCloud
 NATSの            Foundry(2)
メッセージ




   NATSが
  落ちても
 Serviceは
動くはず?
            Cloud Foundry The building of the Open PaaS OSCON2011
               http://www.slideshare.net/derekcollison/oscon-2011
まとめ
1. NATSはEventMachineを使ったPub/Sub
   メッセージングシステム
2. コード量は小さめだし、
   コード、テスト(spec)ともに丁寧なので
   Ruby初級者にもお勧め
3. Cluster対応版はまだですか?
質問タイム
サンプルを動かす4
 authentication
サンプルを動かす5
   reply
NATSの概要
    他のPaaSでのmessagingの実装
heroku      不明   RoutingはErlangベースの独自実装

GAE         不明   RabbitMQのProjects involving
                 RabbitMQに”App Engine
                 imprementation”とあるが何に使ってい
                 るかは不明
AppScale    不明   未調査
TyphoonAE



• 情報お待ちしております<(_ _)>

Reading NATS

  • 1.
    第1回 Cloud Foundry輪読会 NATSを んだ。 NATSを読んだ。 Katsunori Kawaguchi @hamakn 2011-10-18
  • 2.
    Cloud Foundryのmessagingに 利用されている、『NATS』の コードを読んだので、 そのまとめを、 デモを交えつつ 共有したいと思います。
  • 3.
  • 4.
    自己紹介 • 川口 克則@hamakn • NTTコム所属 • Web/スマートフォンアプリの開発 主にRails • 社内PaaSの第一候補として Cloud Foundryを検証中(2011年10月~)
  • 5.
  • 6.
    NATSとCloud Foundry この 実装が NATS Cloud Foundry The building of the Open PaaS OSCON2011 http://www.slideshare.net/derekcollison/oscon-2011
  • 7.
    NATSとCloud Foundry(2) 青い 矢印が NATSの メッセージ Cloud Foundry The building of the Open PaaS OSCON2011 http://www.slideshare.net/derekcollison/oscon-2011
  • 8.
    NATS https://github.com/derekcollison/nats/ •A lightweight EventMachine based publish-subscribe messaging system. • Rubyで実装 • 依存gem – eventmachine, json_pure, daemons, thin • ver0.4.10ではsingle server design < SPOF
  • 9.
    publish-subscribe messaging 受信側はtopicを subscribe 送信側はメッセージを topicにpublish • topicを介して多対多で通信する メッセージングモデル • メリット:スケールさせやすい/疎結合にしやすい
  • 10.
    EventMachine http://rubyeventmachine.com/ • Fast, simple event-processing library for Ruby programs. • 非同期I/O処理を行えるライブラリ • Reactor pattern – Rubyだと他にcool.io(旧rev)など – 他言語であればnode.js, AnyEvent, Twistedなど • 利用例 – thin(httpd), em-websocketなどなど
  • 11.
    Reactor pattern • シングルスレッドの イベントループで 非同期I/Oを実現する デザインパターン
  • 12.
    EventMachineのサンプル1 エコーサーバ require 'eventmachine' module Echo def receive_data(data) send_data(data) end end EM.run do EM.start_server("0.0.0.0", 10000, Echo) end デモ
  • 13.
    EventMachineのサンプル2 HTTPクライアント require 'eventmachine' hosts = [“www.google.co.jp”, “www.yahoo.co.jp”] hosts_size = hosts.size EM.run do hosts.each do |h| http = EM::Protocols::HttpClient.request(:host => h, :port => 80, :request => “/”) http.callback do |response| p response[:status] EM.stop if (hosts_size -= 1) <= 0 end end end デモ
  • 14.
    ここまでのまとめ 1. Cloud FoundryはNATSを使っている 2.NATSはEventMachineを使ったPub/Sub メッセージングシステム 3. Pub/Subはメッセージングの一方式 4. EventMachineはReactorパターンによる 非同期I/Oを行うためのライブラリ 5. EventMachineのサンプルを動かして なんとなく慣れた
  • 15.
  • 16.
    ファイル構成 • lib nats/client.rb NATSクライアント nats/server.rb NATSサーバの起動 nats/server/server.rb NATSサーバ本体 nats/server/connection.rb コネクションのメッセージ処理など nats/server/sublist.rb Subscriberのリスト管理 nats/server/options.rb 起動オプションのパース nats/ext/ JrubyやRuby1.8.6へのパッチなど • bin サーバやクライアントの起動コマンド • spec テストコード • examples サンプルコード • benchmark ベンチーマークコード • lib “cluster” branchのみ nats/server/cluster.rb NATSサーバを束ねるクラスタ本体 nats/server/route.rb クラスタ構成時のルーティング
  • 17.
    サンプルを動かす1 Sub subject:foo Pub NATS Sub subject:foo subject:foo message:hello Server Sub subject:bar デモ
  • 18.
    サンプルを動かす2 Sub subject:foo.> Pub subject:foo.bar message:hello NATS Sub subject:foo.* Server Pub subject:foo.bar.hoge message:hello Sub subject:foo デモ
  • 19.
    サンプルを動かす3 queue Sub subject:foo Pub NATS Sub subject:foo subject:foo message:hello Server 3つのうち Sub どれか1つにpublish subject:foo デモ
  • 20.
    NATSサーバの起動 @ lib/nats/server.rb 25行目~ • 左:EMのechoサーバ • 右:NATSサーバの開始 require 'eventmachine' EM.run do EM.start_server( module Echo NATSD::Server.host, def receive_data(data) NATSD::Server.port, send_data(data) NATSD::Connection end ) end end EM.run do EM.start_server("0.0.0.0", 10000, Echo) Echo end
  • 21.
    メッセージの送信 • Subscribe NATS.start NATS.subscribe(subject) {|msg, _, sub| puts “#{header} Receive on [#{sub}] : ‘#{msg}’” } end (@ bin/nats-sub 35行目) • Publish NATS.start NATS.publish(subject, msg) { NATS.stop } end (@ bin/nats-pub 23行目)
  • 22.
    NATSのプロトコル “OP foo queue 2/r/n” 的メッセージが飛ぶ OPが命令 • クライアント→サーバ • サーバ→クライアント – PUB – MSG – SUB – OK – UNSUB – ERR – PING – PING – PONG – PONG – CONNECT – INFO – INFO – UNKNOWN – UNKNOWN • lib/nats/server/connection.r • lib/nats/client.rb 446行目~ b 57行目~ に受信処理 に受信処理
  • 23.
    メッセージングの例 サンプルを動かす1 の場合 Server Sub Pub INFO => * * <= CONNECT * <= SUB foo INFO => * * <= CONNECT * <= PUB foo hello! MSG hello! => hello!
  • 24.
    Sublistの管理 @ lib/nats/server/sublist.rb • subject “foo”, “bar”, “foo.*”, “foo.>” を実現する仕組み Struct Subscriber :conn NATSD::Connectionのインスタンス struct SublistLevel :nodes subject => SublistNodeのハッシュ :pwc subject=“*”時のSublistNode :fwc subject=“>”時のSublistNode struct SublistNode :leaf_nodes NATSD::Subscriber の配列 :next_level SublistLevel
  • 25.
  • 26.
    NATSの問題点 • 現状single server •“cluster” blanchが存在 • 設計方針 Cluster Design Overview https://github.com/derekcollison/nats/ wiki/Cluster-Design
  • 27.
    なぜNATSなのか? • 他の案 – AMQP(RabbitMQ) – Storm – RestMS – XMPP • RubyWorld Conf. / Why ruby? – Allows great productivity and rapid iteration – Language perfomance is not always key
  • 28.
    Cloud FoundryでのNATS (ちょっとだけ)
  • 29.
    NATS Server(NATSD)の起動 • @bin/vcap `#{nats_server} –p #{@uri.port} –P #{@pid_file} –d 2> /dev/null` • 現状、全てのvcapサーバで nats serverが動作してしまう (本来 mbus:// で指定されるサーバ以外は不要)
  • 30.
    青い 矢印が NATSとCloud NATSの Foundry(2) メッセージ NATSが 落ちても Serviceは 動くはず? Cloud Foundry The building of the Open PaaS OSCON2011 http://www.slideshare.net/derekcollison/oscon-2011
  • 31.
    まとめ 1. NATSはEventMachineを使ったPub/Sub メッセージングシステム 2. コード量は小さめだし、 コード、テスト(spec)ともに丁寧なので Ruby初級者にもお勧め 3. Cluster対応版はまだですか?
  • 32.
  • 34.
  • 35.
  • 36.
    NATSの概要 他のPaaSでのmessagingの実装 heroku 不明 RoutingはErlangベースの独自実装 GAE 不明 RabbitMQのProjects involving RabbitMQに”App Engine imprementation”とあるが何に使ってい るかは不明 AppScale 不明 未調査 TyphoonAE • 情報お待ちしております<(_ _)>