18
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ScalaでRemote Actorのシンプルな例

Last updated at Posted at 2015-06-21

Remote Actorを使いプロセスやネットワークを超えて、Actorを統合する方法をサンプルを示しながらご紹介します。

こちらのサンプルの動作する完全版はGitHubを御覧ください。suin/akka-sample-remote-scala

Step 1: プロジェクトを作成する

まず、build.sbtを作成します。こちらのサンプルはわけあって古いバージョンのakkaとScalaを使っていますが、最新のバージョンを指定していただいてもいいかと思います。

build.sbt
name := """akka-sample-remote-scala"""

version := "2.3.10"

scalaVersion := "2.10.4"

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.3.3",
  "com.typesafe.akka" %% "akka-remote" % "2.3.3"
)

Step 2: 共有するオブジェクトを定義する

リモートとローカルで送受信するオブジェクトを定義します。

common/package.scala
package suin

package object common {
  case object Hello
}

Step 3: リモートのActor Systemを実装する

リモートのActor Systemをコーディングします。

remote/RemoteApp.scala
package suin.remote

import java.io.File

import akka.actor.{ActorLogging, Props, ActorSystem, Actor}
import com.typesafe.config.ConfigFactory
import suin.common.Hello

object RemoteApp extends App {
  val configFile = getClass.getClassLoader.getResource("remote_application.conf").getFile
  val config = ConfigFactory.parseFile(new File(configFile))
  val system = ActorSystem("remote-system", config)
  val remote = system.actorOf(Props[RemoteActor], name="remote")
  system.log.info("Remote is ready")
}

class RemoteActor extends Actor with ActorLogging {
  override def receive: Receive = {
    case Hello =>
      log.info("Remote received {} from {}", Hello, sender)
      sender ! Hello
    case msg: String =>
      log.info("Remote received {} from {}", msg, sender)
      sender ! "hi"
    case any =>
      log.info("Remote received unknown message {} from {}", any, sender)
  }
}

次に、リモートの設定ファイルを作成します。

remote-application.conf
akka {
  loglevel = "INFO"
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }
  remote {
    enabled-transports = ["akka.remote.netty.tcp"]
    netty.tcp {
      hostname = "127.0.0.1"
      port = 5150
    }
    log-sent-messages = on
    log-received-messages = on
  }
}

Step 4: ローカルのActor Systemを実装する

ローカルのActor Systemをコーディングします。

local/LocalApp.scala
package suin.local

import java.io.File

import akka.actor.{ActorLogging, Props, ActorSystem, Actor}
import com.typesafe.config.ConfigFactory
import suin.common.Hello

class LocalActor extends Actor with ActorLogging {
  @throws[Exception](classOf[Exception])
  override def preStart(): Unit = {
    val remoteActor = context.actorSelection(LocalApp.config.getString("app.remote-system.remote-actor"))
    log.info("Remote actor is {}", remoteActor)
    remoteActor ! "hi"
    remoteActor ! Hello
  }

  override def receive: Receive = {
    case msg: String =>
      log.info("Client received {} from {}", msg, sender)
    case Hello =>
      log.info("Client received {} from {}", Hello, sender)
    case any =>
      log.info("Client received unknown message {} from {}", any, sender)
  }
}

object LocalApp extends App {
  val configFile = getClass.getClassLoader.getResource("local_application.conf").getFile
  val config = ConfigFactory.parseFile(new File(configFile))
  val system = ActorSystem("client-system", config)
  val localActor = system.actorOf(Props[LocalActor], name = "local")
}

ローカルの設定ファイルを作成します。

local_application.conf
akka {
  loglevel = "INFO"
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }
  remote {
    enabled-transports = ["akka.remote.netty.tcp"]
    netty.tcp {
      hostname = "127.0.0.1"
      port = 0 # any free port
    }
    log-sent-messages = on
    log-received-messages = on
  }
}

app.remote-system.remote-actor = "akka.tcp://remote-system@127.0.0.1:5150/user/remote"

Step 5: ビルドして実行する

ターミナルを2つ立ち上げます。

ひとつのターミナルでリモートのActor Systemを起動します。

% ./activator run
[info] Loading project definition from /Users/suin/Desktop/akka-sample-remote-scala/project
[info] Set current project to akka-sample-remote-scala (in build file:/Users/suin/Desktop/akka-sample-remote-scala/)

Multiple main classes detected, select one to run:

 [1] suin.local.LocalApp
 [2] suin.remote.RemoteApp

Enter number: 2

もうひとつのターミナルでローカルのActor Systemを起動します。

% ./activator run
[info] Loading project definition from /Users/suin/Desktop/akka-sample-remote-scala/project
[info] Set current project to akka-sample-remote-scala (in build file:/Users/suin/Desktop/akka-sample-remote-scala/)

Multiple main classes detected, select one to run:

 [1] suin.local.LocalApp
 [2] suin.remote.RemoteApp

Enter number: 1

実行結果がそれぞれコンソールに表示されます。

リモート
[info] Running suin.remote.RemoteApp
[INFO] [06/21/2015 17:02:15.641] [run-main-0] [Remoting] Starting remoting
[INFO] [06/21/2015 17:02:15.799] [run-main-0] [Remoting] Remoting started; listening on addresses :[akka.tcp://remote-system@127.0.0.1:5150]
[INFO] [06/21/2015 17:02:15.801] [run-main-0] [Remoting] Remoting now listens on addresses: [akka.tcp://remote-system@127.0.0.1:5150]
[INFO] [06/21/2015 17:02:15.814] [run-main-0] [ActorSystem(remote-system)] Remote is ready
[INFO] [06/21/2015 17:03:21.080] [remote-system-akka.actor.default-dispatcher-3] [akka.tcp://remote-system@127.0.0.1:5150/user/remote] Remote received hi from Actor[akka.tcp://client-system@127.0.0.1:59552/user/local#167765235]
[INFO] [06/21/2015 17:03:21.081] [remote-system-akka.actor.default-dispatcher-3] [akka.tcp://remote-system@127.0.0.1:5150/user/remote] Remote received Hello from Actor[akka.tcp://client-system@127.0.0.1:59552/user/local#167765235]
ローカル
[info] Running suin.local.LocalApp
[INFO] [06/21/2015 17:03:20.763] [run-main-0] [Remoting] Starting remoting
[INFO] [06/21/2015 17:03:20.898] [run-main-0] [Remoting] Remoting started; listening on addresses :[akka.tcp://client-system@127.0.0.1:59552]
[INFO] [06/21/2015 17:03:20.900] [run-main-0] [Remoting] Remoting now listens on addresses: [akka.tcp://client-system@127.0.0.1:59552]
[INFO] [06/21/2015 17:03:20.911] [client-system-akka.actor.default-dispatcher-2] [akka.tcp://client-system@127.0.0.1:59552/user/local] Remote actor is ActorSelection[Anchor(akka.tcp://remote-system@127.0.0.1:5150/), Path(/user/remote)]
[INFO] [06/21/2015 17:03:21.092] [client-system-akka.actor.default-dispatcher-2] [akka.tcp://client-system@127.0.0.1:59552/user/local] Client received hi from Actor[akka.tcp://remote-system@127.0.0.1:5150/user/remote#-68561685]
[INFO] [06/21/2015 17:03:21.093] [client-system-akka.actor.default-dispatcher-2] [akka.tcp://client-system@127.0.0.1:59552/user/local] Client received Hello from Actor[akka.tcp://remote-system@127.0.0.1:5150/user/remote#-68561685]

参考: A Simple Akka Remote example

18
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?