Hello, dRuby

特に利用目的はありませんがdRuby触ってみます。

単に1台のマシン上で動かすのでは面白くないので、C RubyJRubyの間でのプロセス間通信も試してみます。

動作環境

サーバ側スクリプト

今回はCRubyで動かしています。単純にハッシュに対する値の出し入れをするだけのものです。

store.rb

require 'drb/drb'

class Store
  def initialize
    @hash = {}
  end

  def put(key, value)
    @hash[key] = value
  end

  def get(key)
    @hash[key]
  end

  def keys
    @hash.keys
  end
end

uri = ARGV.shift
DRb.start_service("druby://:10080", Store.new)
puts "service started."
sleep

実行結果:

% ruby store.rb
service started.

クライアント (CRubyその1)

IRBから、先ほどのリモートオブジェクトを指すDRbObjectオブジェクトを作成します。当然通常のRubyオブジェクトと同様に読み書きできています。

% irb -rdrb/drb

> irb -rdrb/drb
irb(main):001:0> remote = DRbObject.new_with_uri('druby://localhost:10080')
=> #<Store:0x842568c>
irb(main):002:0> remote.put('hello', 'world')
=> "world"
irb(main):003:0> remote.get('hello')
=> "world"

クライアント (JRuby)

次に、JRubyIRBから、先ほどのリモートオブジェクトの値を参照します。先ほどCRubyクライアント経由で書き込んだ値が反映されていること (→リモートオブジェクトの実体はサーバ側にあること) が確認できます。
さらに、新規のキーをリモートオブジェクトに追加します。

% jirb -rdrb/drb
irb(main):001:0> remote = DRbObject.new_with_uri("druby://localhost:10080")
=> #<DRb::DRbObject:0x1a80aea @uri="druby://localhost:10080", @ref=nil>
irb(main):002:0> remote.get("hello")
=> "world"
irb(main):003:0> remote.put("merry", "christmas")
=> "christmas"
irb(main):004:0> remote.get("merry")
=> "christmas"

クライアント (CRubyその2)

最後に、先ほどのCRuby側IRBクライアントから、JRuby側でセットしたキーが見えることを確認します。

irb(main):004:0> remote.get("merry")
=> "christmas"
irb(main):005:0> remote.keys
=> ["hello", "merry"]

メモ

環境依存の問題と思われますが、サーバ側: CRuby、クライアント側: JRubyの組み合わせで、DRb.start_serviceの引数を "druby//:10080" の代わりに "druby://localhost:10080" とすると、クライアントからうまく接続できないという現象が発生しました。

% jirb -rdrb/drb
irb(main):001:0> remote = DRbObject.new_with_uri("druby://localhost:10080")
=> #<DRb::DRbObject:0x164b9b6 @uri="druby://localhost:10080", @ref=nil>
irb(main):002:0> remote.keys
DRb::DRbConnError: druby://localhost:10080 - #<Errno::ECONNREFUSED: Connection refused - Connection refused>

おそらくJRubylocalhostを指定したときにループバックインタフェースではなくeth0に接続しに行っていると推測しましたが、それ以上は追跡していません。