Ruby 2.4.0 リファレンスマニュアル > ライブラリ一覧 > drbライブラリ

library drb

要約

分散オブジェクトプログラミングのためのライブラリです。

Ruby のプロセスから他のRubyプロセスにあるオブジェクトのメソッド を呼びだすことができます。他のマシン上のプロセスにも アクセスできます。

概要

dRuby は Ruby 専用の分散オブジェクトシステムです。 Ruby のみで記述され、TCP socket のような Ruby 本体が提供する 通信手段があれば追加のインストール物なしに利用可能です。 独自のプロトコルで通信し、他の分散オブジェクトシステム (CORBA, RMI, .NETなど)との相互運用性はありません。

dRuby は

ができます。これらはすべて透過的に行われます。

リモートプロセスにあるオブジェクトはローカルには DRb::DRbObject の インスタンスとして表現されます。このオブジェクトはリモートオブジェクトの proxy のように振舞います。つまり、このオブジェクトのメソッドを呼び出すと リモートオブジェクトに転送されます。 CORBA の IDL のようなリモートオブジェクトのインターフェースを 静的に宣言する必要はなく、すべては実行時に解決されます。

リモートプロセスからのメソッド呼出しはそれを受け取ったプロセスの DRb::DRbServer オブジェクトが処理します。 受け取ったメッセージからメソッド呼出し情報を取り出し、ローカルにある オブジェクトを特定し、 そのメソッドを呼び出し、返り値をリモートの呼び出し元に送ります。 どのようなオブジェクトのメソッドも呼びだすことができます。 何か特別なインターフェースを実装したり、特別な mixin を必要としたりは しません。 オブジェクトの特定は DRb::DRbServer が自動でします。そのため オブジェクトの登録のようなことは通常必要ありません。

DRb::DRbServer に URI(例: druby://example.com:8787)を関連付けること で、他のプロセスからの通信(リモートメソッド呼び出し)ができるようになります (逆に言うと、URIを指定しないことで、他のプロセスからのリモートメソッド 呼び出しを拒否することができます)。 また、DRb::DRbServer に「フロントオブジェクト」を登録しておくと、 サーバの URI からそのオブジェクトをリモートオブジェクト として取り出すことができます。通常はこのオブジェクトから辿って 必要な(リモート)オブジェクトを取り出します。

リモートメソッド呼び出しはかなりの部分、同じプロセス内の オブジェクトのメソッドを呼び出すのと同じ動作をします。 ブロック付きのメソッド呼び出しもできますし、 リモートプロセス上で生じた例外はローカルプロセス上に 転送されます。DRb 関連の例外は DRb::DRbError の サブクラスです。

リモートメソッド呼び出しの引数や返り値には任意の Ruby オブジェクト が使えます。デフォルトではオブジェクトをマーシャリングして 渡され、受け取った側が元のオブジェクトに戻します。つまり オブジェクトはコピーされます。これは通常の同一プロセス上での メソッド呼び出しと大きく異なる点です(通常のメソッド呼び出しでは オブジェクトへのリファレンスが渡されます)。

ただし、マーシャリング不可能なオブジェクトは dRuby によって ある種のリファレンスとして取り扱われます。これは DRb::DRbObject のインスタンスとして表現されます。これはリモートオブジェクトの proxy として動作し、proxy のメソッドを呼び出すと上に説明した通りの 方法でリモートオブジェクトのメソッドを呼び出します。

マーシャンリング可能なオブジェクトを DRbObject でリファレンスとして 渡したい、つまりコピーでなくリファレンスで渡したい場合は そのオブジェクトに DRb::DRbUndumpedModule#include します。

dRuby はブロック付きのメソッド呼び出しをサポートしていますが、 Proc はマーシャリング不可能なので、ブロックの中身は (リモート側でなく)ローカルプロセス上で実行されます。 リモート側がブロックを呼び出そうとすると、ブロックの引数が リモート側からローカル側に(上で説明したようにコピーもしくは dRuby のリファレンス オブジェクトとして)渡され、ブロックが実行され、その返り値がリモート側に 送られます。

セキュリティ

dRuby でインターネット上に公開するサービスを作るべきではありません。 イントラネットのサービスとして動かす場合もセキュリティには気を使う 必要があるでしょう。

あるオブジェクトへの外部からのアクセスを許可すると、単にそのオブジェクトの メソッドを外部から呼び出せるだけでなく、任意の Ruby のコードを実行できて しまいます。例えば以下のようなことができます。

# !! 危険 !!
ro = DRbObject::new_with_uri("druby://your.server.com:8989")
class << ro
  # リモートオブジェクトの instance_eval を呼ぶため
  # ローカルオブジェクトの instance_eval を取り除く
  undef :instance_eval
end
ro.instance_eval("DANGEROUS RUBY CODE!")

このような instance_eval による危険性は $SAFE を 1 以上に することで防げます。 DRb.#start_service の :safe_level オプションで リモートからのメソッド呼び出しのコンテキストで指定されるセーフレベルを 指定できます。

また、DRb::DRbServer にはアクセスコントロールリスト(アクセスを許可/拒否 する IP のリスト)によりアクセス制御をすることができます。 この機能は ACL で実現されています。 このアクセス制御は単体で使うのではなく、 適切なファイアウォールと併用すべきです。

リファレンス

Example

単純なクライアント-サーバシステムの例。

ターミナルを2つサーバ側/クライアント側として起動して、サーバ側を 先に動かしてください。

サーバ側コード

require 'drb/drb'

# 通信を待ち受ける URI
URI="druby://localhost:8787"

class TimeServer

  def get_current_time
    return Time.now
  end

end

# サーバ側でリクエストを受け付けるオブジェクト
FRONT_OBJECT=TimeServer.new

# サーバを起動する
DRb.start_service(URI, FRONT_OBJECT, :safe_level => 1)
# DRb のスレッドが終了するのを待つ
DRb.thread.join

クライアント側コード

require 'drb/drb'

# 接続先の URI
SERVER_URI="druby://localhost:8787"

# DRbサーバを起動する
# この例には必要ないが、front オブジェクト以外の
# リモートオブジェクトのメソッドを呼び出す時には必要
DRb.start_service
# リモートオブジェクトの取得
timeserver = DRbObject.new_with_uri(SERVER_URI)
# リモートメソッドの呼び出し
puts timeserver.get_current_time

クラス

DRb::DRbIdConv

オブジェクトと識別子を相互に変換するクラスです。

DRb::DRbObject

リモートの dRuby オブジェクトを表すオブジェクトです。

DRb::DRbServer

dRuby サーバクラス。

DRb::DRbUnknown

リモートプロセスからマーシャリングされて送られてきたオブジェクトで、 そのクラスがローカルプロセス内では不明であるようなものを 表すクラス。

DRbIdConv

Alias of DRb::DRbIdConv

DRbObject

Alias of DRb::DRbObject

モジュール

DRb

drb ライブラリの名前空間となるモジュール。

DRb::DRbProtocol

drb で使われる通信プロトコルを取り扱うモジュールです。

DRb::DRbUndumped

このモジュールをインクルードしたクラスのインスタンスは ネットワーク越しに参照渡しで渡されるようになります。 値渡し出来ないオブジェクトを drb と一緒に使う時に有用です。

DRbUndumped

Alias of DRb::DRbUndumped

例外クラス

DRb::DRbError

drb ライブラリ固有の例外を表すクラス

  DRb::DRbBadScheme

プロトコルクラスが受け取った URI の schema が そのクラスでサポートされていないことを、伝えるための例外。

  DRb::DRbBadURI

URI に含まれている schema をサポートしているプロトコルが見付からない ことを意味する例外クラス。

  DRb::DRbConnError

通信エラーが発生したことを意味する例外クラス。

  DRb::DRbRemoteError

例外オブジェクトを wrap したクラス

  DRb::DRbServerNotFound

カレントサーバが見付からない場合に発生する例外のクラス

  DRb::DRbUnknownError

DRb::DRbUnknown をラップする例外クラスです。

サブライブラリ

drb/acl

drb で用いる ACL(Access Control List)を定義するライブラリ。

drb/extserv

DRb::ExtServ を定義しているライブラリ。

drb/extservm

DRb::ExtServManager を定義しているライブラリ。

drb/gw

drb 通信を中継するゲートウェイ(DRb::GW)と、 中継に必要なオブジェクト識別子変換クラス(DRb::GWIdConv)、 および DRb::DRbObject への拡張が含まれています。

drb/observer

DRb 用の修正をした Observable (DRb::DRbObservable) を定義するライブラリ。

drb/ssl

DRb のプロトコルとして SSL/TLS 上で通信する drbssl が使えるようになります。

drb/timeridconv

DRb::DRbIdConv の拡張 DRb::TimerIdConv を定義 するライブラリ。 DRb::DRbIdConv の GC 問題をタイムアウトを定めることで 部分的に解決します。

drb/unix

DRb のプロトコルとして UNIX ドメインソケット経由で通信する drbunix が使えるようになります。