Scala での簡単な RemoteActor

Scala の Actor 用 API では、リモートプロセスを含むプロセス間通信を実現するための API が用意されているので、今回はこれを試してみる事にする。

RemoteActor の使い方

RemoteActor を実現するには、scala.actors.Actor オブジェクトのメソッドに加え、scala.actors.remote.RemoteActor オブジェクトの各種メソッドを使う事になる。
基本的に、actor や receive メソッドに以下のような RemoteActor 用のメソッドを組み合わせればよい。

  • alive メソッドで待ち受けるポート番号を指定
  • register メソッドで RemoteActor 対象の Actor にシンボルを付ける
  • select メソッドで呼び出す RemoteActor を特定する

とりあえず、簡単な RemoteActor のサンプルを作成してみると以下のようになる。通常の Actor の定義に alive と register メソッドの実行を組み合わせるだけ。

consumerTest.scala(RemoteActor)
import scala.actors.Actor._
import scala.actors.remote.RemoteActor._

object consumerTest extends Application {
    actor {
        //ポート番号の設定
        alive(9000)
        //シンボルの設定
        register('testActor, self)

        loop {
            receive {
                case msg => {
                    println("received=" + msg)
                    reply("rec-" + msg)
                }
            }
        }
    }
}

次に RemoteActor を呼び出す方を作成すると以下のようになる。select メソッドを使って RemoteActor を取得すれば、通常の Actor と同様に ! や !? メソッドでメッセージを送信する。

producerTest.scala(RemoteActor呼び出し)
import scala.actors.Actor._
import scala.actors.remote.Node
import scala.actors.remote.RemoteActor._

object producerTest extends Application {
    override def main(args: Array[String]) {
        if (args.length < 1) {
            println(">scala producerTest [numer]")
            return
        }

        actor {
            //ノード(ホスト名、ポート番号)とシンボルを指定して
            //RemoteActor を取得
            val consumer = select(Node("localhost", 9000), 'testActor)

            //実行時引数の1番目をそのまま RemoteActor に送信
            consumer !? args(0) match {
                case msg => println("result=" + msg)
            }
        }
    }
}
実行例

まず、RemoteActor を実行しておく。

>scalac consumerTest.scala
>scala consumerTest

次に、別プロセスとして呼び出し側を実行する。

>scalac producerTest.scala
>scala producerTest test

以下のような結果となり、プロセス間の通信が容易に実現できた。

・・・
>scala consumerTest
received=test
・・・
>scala producerTest test
result=rec-test