如果我正确理解了这个问题,那么我可以提供几种方法来实现这一点(当然还有其他方法)。
选项 1
在这种方法中,将有一个参与者负责定期唤醒并向所有会话参与者发送请求以获取其当前统计信息。该演员将使用带有通配符的ActorSelection 来实现该目标。如果这种方法的代码大致如下:
case class SessionStats(foo:Int, bar:Int)
case object GetSessionStats
class SessionActor extends Actor{
def receive = {
case GetSessionStats =>
println(s"${self.path} received a request to get stats")
sender ! SessionStats(1, 2)
}
}
case object GatherStats
class SessionStatsGatherer extends Actor{
context.system.scheduler.schedule(5 seconds, 5 seconds, self, GatherStats)(context.dispatcher)
def receive = {
case GatherStats =>
println("Waking up to gether stats")
val sel = context.system.actorSelection("/user/session*")
sel ! GetSessionStats
case SessionStats(f, b) =>
println(s"got session stats from ${sender.path}, values are $f and $b")
}
}
然后您可以使用以下代码测试此代码:
val system = ActorSystem("test")
system.actorOf(Props[SessionActor], "session-1")
system.actorOf(Props[SessionActor], "session-2")
system.actorOf(Props[SessionStatsGatherer])
Thread.sleep(10000)
system.actorOf(Props[SessionActor], "session-3")
因此,使用这种方法,只要我们使用命名约定,我们就可以使用带有通配符的演员选择来始终找到所有会话演员,即使他们不断地来(开始)和去(停止)。
选项 2
有点类似的方法,但在这个方法中,我们使用一个集中的 Actor 来生成会话 Actor 并充当它们的监督者。这个中心参与者还包含定期轮询统计信息的逻辑,但由于它是父节点,因此它不需要ActorSelection,而可以只使用它的children 列表。看起来像这样:
case object SpawnSession
class SessionsManager extends Actor{
context.system.scheduler.schedule(5 seconds, 5 seconds, self, GatherStats)(context.dispatcher)
var sessionCount = 1
def receive = {
case SpawnSession =>
val session = context.actorOf(Props[SessionActor], s"session-$sessionCount")
println(s"Spawned session: ${session.path}")
sessionCount += 1
sender ! session
case GatherStats =>
println("Waking up to get session stats")
context.children foreach (_ ! GetSessionStats)
case SessionStats(f, b) =>
println(s"got session stats from ${sender.path}, values are $f and $b")
}
}
并且可以进行如下测试:
val system = ActorSystem("test")
val manager = system.actorOf(Props[SessionsManager], "manager")
manager ! SpawnSession
manager ! SpawnSession
Thread.sleep(10000)
manager ! SpawnSession
现在,这些示例非常琐碎,但希望它们能够为您描绘如何使用ActorSelection 或管理/监督动态解决此问题。还有一个好处是ask 既不需要也不需要阻塞。