Akka 2.1远程:跨系统共享参与者
我正在学习Akka 2.1中的远程演员,我试着改编这部电影。 我从控制台实现了一个快速的'n'脏UI来发送滴答声。并通过询问(并显示结果)当前计数退出 其思想是启动一个主节点来运行Counter-actor,并启动一些客户端节点来通过远程处理向其发送消息。然而,我希望通过配置和对代码的最小更改来实现这一点。因此,通过改变配置,可以使用本地参与者 我发现了类似的问题,即即使有许多实例在运行,所有API调用都必须通过一个参与者 我写了类似的配置,但我不能让它工作。我当前的代码确实使用远程处理,但它会在主节点上为每个新节点创建一个新的actor,我无法让它连接到现有的actor,而不显式地给它路径(并且无视配置点)。然而,这不是我想要的,因为状态不能以这种方式在JVM之间共享 完整的可运行代码可用 这是我的配置文件Akka 2.1远程:跨系统共享参与者,akka,actor,remote-actors,Akka,Actor,Remote Actors,我正在学习Akka 2.1中的远程演员,我试着改编这部电影。 我从控制台实现了一个快速的'n'脏UI来发送滴答声。并通过询问(并显示结果)当前计数退出 其思想是启动一个主节点来运行Counter-actor,并启动一些客户端节点来通过远程处理向其发送消息。然而,我希望通过配置和对代码的最小更改来实现这一点。因此,通过改变配置,可以使用本地参与者 我发现了类似的问题,即即使有许多实例在运行,所有API调用都必须通过一个参与者 我写了类似的配置,但我不能让它工作。我当前的代码确实使用远程处理,但它会
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
deployment {
/counter {
remote = "akka://ticker@127.0.0.1:2552"
}
}
}
remote {
transport = "akka.remote.netty.NettyRemoteTransport"
log-sent-messages = on
netty {
hostname = "127.0.0.1"
}
}
}
和完整来源
import akka.actor._
import akka.pattern.ask
import scala.concurrent.duration._
import akka.util.Timeout
import scala.util._
case object Tick
case object Get
class Counter extends Actor {
var count = 0
val id = math.random.toString.substring(2)
println(s"\nmy name is $id\ni'm at ${self.path}\n")
def log(s: String) = println(s"$id: $s")
def receive = {
case Tick =>
count += 1
log(s"got a tick, now at $count")
case Get =>
sender ! count
log(s"asked for count, replied with $count")
}
}
object AkkaProjectInScala extends App {
val system = ActorSystem("ticker")
implicit val ec = system.dispatcher
val counter = system.actorOf(Props[Counter], "counter")
def step {
print("tick or quit? ")
readLine() match {
case "tick" => counter ! Tick
case "quit" => return
case _ =>
}
step
}
step
implicit val timeout = Timeout(5.seconds)
val f = counter ? Get
f onComplete {
case Failure(e) => throw e
case Success(count) => println("Count is " + count)
}
system.shutdown()
}
我使用了
sbt-run
并在另一个窗口sbt-run-Dakka.remote.netty.port=0
来运行它。我尝试了你的git项目,除了编译错误外,它实际上运行得很好,并且你必须用jvm的-Dakka.remote.netty.port=0
参数启动sbt会话,不作为运行的参数
您还应该了解,您不必在这两个过程中都启动计数器。在本例中,它打算从客户端创建并部署在服务器上(端口2552)。您不必在服务器上启动它。对于本例,在服务器上创建actor系统就足够了。我发现我可以使用某种模式。Akka remote只允许在远程系统上部署(无法找到一种方法使其仅通过配置就可以在远程系统上进行查找..我错了吗?) 所以我可以部署一个“侦察机”来传回ActorRef。在分支“scout hack”下的原始回购上可用的可运行代码。因为这感觉像一个黑客。我仍然会欣赏基于配置的解决方案 演员
case object Fetch
class Scout extends Actor{
def receive = {
case Fetch => sender ! AkkaProjectInScala._counter
}
}
反角色创建现在是懒惰的
lazy val _counter = system.actorOf(Props[Counter], "counter")
所以它只在主机上执行(由端口决定),并且可以像这样获取
val counter: ActorRef = {
val scout = system.actorOf(Props[Scout], "scout")
val ref = Await.result(scout ? Fetch, timeout.duration) match {
case r: ActorRef => r
}
scout ! PoisonPill
ref
}
和完整配置
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
deployment {
/scout {
remote = "akka://ticker@127.0.0.1:2552"
}
}
}
remote {
transport = "akka.remote.netty.NettyRemoteTransport"
log-sent-messages = on
netty {
hostname = "127.0.0.1"
}
}
}
编辑:我还找到了一个干净的方法:检查“反向路径”的配置,如果存在actor,则检查(路径)的配置,否则创建actor。很好,运行时可以注入master,代码比使用“scout”要干净得多,但它仍然需要决定查找或创建参与者的天气。我想这是不可避免的。修复了代码。更改参数不会更改行为。它能工作,但不是我想要的方式。重新表述我的问题:我如何(如果可能)配置akka,使其不为每个客户创建新的参与者,而是共享现有的参与者?