読者です 読者をやめる 読者になる 読者になる

夢とガラクタの集積場

落ちこぼれ三流エンジニアである管理人の夢想=『夢』と、潰えた夢=『ガラクタ』の集積場です。

Akka-RemoteでRemoteからActorを作成する

こんにちは。

前回に続き、今回はAkka-Remoteを使用してリモートからActorを作成する方法を確認します。

1. プログラム上でアドレスを定義してデプロイ

まずは、プログラム上でアドレスを定義してServer側にActorを生成することを試してみます。

クライアント側のアプリケーションを下記のように修正します。
■RemoteClientApp.scala

import akka.actor._
import com.typesafe.config.ConfigFactory
import akka.remote.RemoteScope

/**
 * Akka-Remoteを用いて接続し、メッセージを送信するサンプル
 */
object RemoteClientApp extends App {
  override def main(args: Array[String]): Unit = {
    val config = ConfigFactory.load("conf/remote-client-app.conf")
    implicit val system = ActorSystem.apply("RemoteClientApp", config)
    val remoteActorRef = system.actorSelection("akka.tcp://RemoteServerApp@127.0.0.1:2552/user/Receive")

    val inbox = ActorDSL.inbox()
    remoteActorRef.tell("Remote", inbox.getRef())

    val received1 = inbox.receive()
    println("received1:" + received1)

    val remoteAddress = AddressFromURIString("akka.tcp://RemoteServerApp@127.0.0.1:2552")
    val programRemoteRef = system.actorOf(Props[MessagePrintActor].
      withDeploy(Deploy(scope = RemoteScope(remoteAddress))))
    programRemoteRef.tell("RemoteDeploy", inbox.getRef())
    val received2 = inbox.receive()
    println("received2:" + received2)

    Thread.sleep(10000)
    system.shutdown()
  }
}

下記の記述の個所が実際にServer側にActorをデプロイしている個所になりますね。
scopeを指定することでRemoteにデプロイすることが可能になります。
ただ、Server側もデプロイしようとしているActorのクラスを保持している必要があります。
このあたりが動的にデプロイ可能なのかどうかはもっと調べてからで^^;

    val remoteAddress = AddressFromURIString("akka.tcp://RemoteServerApp@127.0.0.1:2552")
    val programRemoteRef = system.actorOf(Props[MessagePrintActor].
      withDeploy(Deploy(scope = RemoteScope(remoteAddress))))

実行結果は下記の通りです。
■RemoteServerApp

[INFO] [09/27/2014 21:15:22.041] [main] [Remoting] Starting remoting
[INFO] [09/27/2014 21:15:22.363] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://RemoteServerApp@127.0.0.1:2552]
[INFO] [09/27/2014 21:15:22.365] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://RemoteServerApp@127.0.0.1:2552]
[INFO] [09/27/2014 21:15:22.378] [RemoteServerApp-akka.actor.default-dispatcher-3] [akka.tcp://RemoteServerApp@127.0.0.1:2552/user/Receive] akka://RemoteServerApp/user/Receive: Received String Local
[INFO] [09/27/2014 21:15:31.115] [RemoteServerApp-akka.actor.default-dispatcher-3] [akka.tcp://RemoteServerApp@127.0.0.1:2552/user/Receive] akka://RemoteServerApp/user/Receive: Received String Remote
[INFO] [09/27/2014 21:15:31.266] [RemoteServerApp-akka.actor.default-dispatcher-3] [akka.tcp://RemoteServerApp@127.0.0.1:2552/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/$a] akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/$a: Received String RemoteDeploy
[INFO] [09/27/2014 21:16:22.434] [ForkJoinPool-3-worker-7] [Remoting] Remoting shut down

■RemoteClientApp

[INFO] [09/27/2014 21:15:30.542] [main] [Remoting] Starting remoting
[INFO] [09/27/2014 21:15:30.796] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://RemoteClientApp@127.0.0.1:2553]
[INFO] [09/27/2014 21:15:30.798] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://RemoteClientApp@127.0.0.1:2553]
received1:akka://RemoteServerApp/user/Receive: Received String Remote
received2:akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/$a: Received String RemoteDeploy
[INFO] [09/27/2014 21:15:41.402] [ForkJoinPool-3-worker-7] [Remoting] Remoting shut down

リモートからActorをデプロイした場合、
Server側の「/remote/akka.tcp/〜」というパス配下にデプロイされるようですね。

2. 定義でRouterを用いたデプロイは出来る?

次は定義でRouterを用いたデプロイを行ってみます。
まずは事前準備としてクライアント側の定義ファイルを下記のように修正し、
actor.deploymentの定義を追加します。

■remote-client-app.conf

akka {
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }

  actor.deployment {
    /router1 {
    router = round-robin-pool
    nr-of-instances = 3
    remote = "akka.tcp://RemoteServerApp@127.0.0.1:2552"
    }
  }

  remote {
    enabled-transports = ["akka.remote.netty.tcp"]
    netty.tcp {
      hostname = "127.0.0.1"
      port = 2553
    }
 }
}

その上で、クライアント側のアプリケーションを下記のように修正します。
■RemoteClientApp.scala

import akka.actor._
import com.typesafe.config.ConfigFactory
import akka.remote.RemoteScope

/**
 * Akka-Remoteを用いて接続し、メッセージを送信するサンプル
 */
object RemoteClientApp extends App {
  override def main(args: Array[String]): Unit = {
    val config = ConfigFactory.load("conf/remote-client-app.conf")
    implicit val system = ActorSystem.apply("RemoteClientApp", config)

    // リモートのActorに対してメッセージ送信
    val remoteActorRef = system.actorSelection("akka.tcp://RemoteServerApp@127.0.0.1:2552/user/Receive")
    val inbox = ActorDSL.inbox()
    remoteActorRef.tell("Remote", inbox.getRef())
    val received1 = inbox.receive()
    println("received1:" + received1)

    // リモートでActorをデプロイ
    val remoteAddress = AddressFromURIString("akka.tcp://RemoteServerApp@127.0.0.1:2552")
    val programRemoteRef = system.actorOf(Props[MessagePrintActor].
      withDeploy(Deploy(scope = RemoteScope(remoteAddress))))
    programRemoteRef.tell("RemoteDeploy", inbox.getRef())
    val received2 = inbox.receive()
    println("received2:" + received2)

    // リモートでRouterをデプロイ?
    val remoteRouterRef = system.actorOf(Props[MessagePrintActor],
      "router1")
    remoteRouterRef.tell("RemoteRouter3", inbox.getRef())
    val received3 = inbox.receive()
    println("received3:" + received3)
    remoteRouterRef.tell("RemoteRouter4", inbox.getRef())
    val received4 = inbox.receive()
    println("received4:" + received4)
    remoteRouterRef.tell("RemoteRouter5", inbox.getRef())
    val received5 = inbox.receive()
    println("received5:" + received5)
    remoteRouterRef.tell("RemoteRouter6", inbox.getRef())
    val received6 = inbox.receive()
    println("received6:" + received6)

    Thread.sleep(10000)
    system.shutdown()
  }
}

上記のコードを実行すると実行結果は下記のようになりました。
■RemoteServerApp

[INFO] [09/27/2014 21:28:52.195] [main] [Remoting] Starting remoting
[INFO] [09/27/2014 21:28:52.516] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://RemoteServerApp@127.0.0.1:2552]
[INFO] [09/27/2014 21:28:52.518] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://RemoteServerApp@127.0.0.1:2552]
[INFO] [09/27/2014 21:28:52.528] [RemoteServerApp-akka.actor.default-dispatcher-5] [akka.tcp://RemoteServerApp@127.0.0.1:2552/user/Receive] akka://RemoteServerApp/user/Receive: Received String Local
[INFO] [09/27/2014 21:29:15.392] [RemoteServerApp-akka.actor.default-dispatcher-6] [akka.tcp://RemoteServerApp@127.0.0.1:2552/user/Receive] akka://RemoteServerApp/user/Receive: Received String Remote
[INFO] [09/27/2014 21:29:15.518] [RemoteServerApp-akka.actor.default-dispatcher-6] [akka.tcp://RemoteServerApp@127.0.0.1:2552/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/$a] akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/$a: Received String RemoteDeploy
[INFO] [09/27/2014 21:29:15.651] [RemoteServerApp-akka.actor.default-dispatcher-3] [akka.tcp://RemoteServerApp@127.0.0.1:2552/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1] akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1: Received String RemoteRouter3
[INFO] [09/27/2014 21:29:15.659] [RemoteServerApp-akka.actor.default-dispatcher-6] [akka.tcp://RemoteServerApp@127.0.0.1:2552/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1] akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1: Received String RemoteRouter4
[INFO] [09/27/2014 21:29:15.664] [RemoteServerApp-akka.actor.default-dispatcher-3] [akka.tcp://RemoteServerApp@127.0.0.1:2552/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1] akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1: Received String RemoteRouter5
[INFO] [09/27/2014 21:29:15.668] [RemoteServerApp-akka.actor.default-dispatcher-6] [akka.tcp://RemoteServerApp@127.0.0.1:2552/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1] akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1: Received String RemoteRouter6
[INFO] [09/27/2014 21:29:52.563] [ForkJoinPool-3-worker-7] [Remoting] Remoting shut down

■RemoteClientApp

[INFO] [09/27/2014 21:29:14.812] [main] [Remoting] Starting remoting
[INFO] [09/27/2014 21:29:15.075] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://RemoteClientApp@127.0.0.1:2553]
[INFO] [09/27/2014 21:29:15.077] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://RemoteClientApp@127.0.0.1:2553]
received1:akka://RemoteServerApp/user/Receive: Received String Remote
received2:akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/$a: Received String RemoteDeploy
received3:akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1: Received String RemoteRouter3
received4:akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1: Received String RemoteRouter4
received5:akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1: Received String RemoteRouter5
received6:akka://RemoteServerApp/remote/akka.tcp/RemoteClientApp@127.0.0.1:2553/user/router1: Received String RemoteRouter6
[INFO] [09/27/2014 21:29:25.773] [ForkJoinPool-3-worker-7] [Remoting] Remoting shut down

定義ファイルに記述したServerに対してMessagePrintActorをデプロイすることは出来ましたが、
Routerにはならず、単体Actorとしてのデプロイになってしまったようですね。

ともあれ、定義ファイルからアドレスを読み込んでデプロイすることは出来ました。
次回はRemoteでRouter化するためにはどうすればいいか確認してみます。