您可以在akka啓動文件或您自己的ServletContextListener中啓動您的演員,以便它們在不受綁定到servlet的情況下啓動。 然後,您可以使用akka註冊表查找它們。
Actor.registry.actorFor[MyActor] foreach { _ !! (("Run",id), 10000) }
除此之外,此刻還沒有真正的akka與scalatra的整合。 因此,直到現在,您所能做的最好的方式是對一羣演員使用阻止請求。
我不確定,但我不會爲每個請求產生一個actor,而是有一個可以發送這些請求的小部件actor的池。如果您使用管理員層次結構,那麼您可以使用管理員來調整池的大小,如果它太大或太小。
class MyContextListener extends ServletContextListener {
def contextInitialized(sce: ServletContextEvent) {
val factory = SupervisorFactory(
SupervisorConfig(
OneForOneStrategy(List(classOf[Exception]), 3, 1000),
Supervise(actorOf[WidgetPoolSupervisor], Permanent)
}
def contextDestroyed(sce: ServletContextEvent) {
Actor.registry.shutdownAll()
}
}
class WidgetPoolSupervisor extends Actor {
self.faultHandler = OneForOneStrategy(List(classOf[Exception]), 3, 1000)
override def preStart() {
(1 to 5) foreach { _ =>
self.spawnLink[MyWidgetProcessor]
}
Scheduler.schedule(self, 'checkPoolSize, 5, 5, TimeUnit.MINUTES)
}
protected def receive = {
case 'checkPoolSize => {
//implement logic that checks how quick the actors respond and if
//it takes to long add some actors to the pool.
//as a bonus you can keep downsizing the actor pool until it reaches 1
//or until the message starts returning too late.
}
}
}
class ScalatraApp extends ScalatraServlet {
get("/run/:id") {
// the !! construct should not appear anywhere else in your code except
// in the scalatra action. You don't want to block anywhere else, but in a
// scalatra action it's ok as the web request itself is synchronous too and needs to
// to wait for the full response to have come back anyway.
Actor.registry.actorFor[MyWidgetProcessor] foreach {
_ !! ((Run, id), 10000)
} getOrElse {
throw new HeyIExpectedAResultException()
}
}
}
請不要考慮上面的代碼,如發生這種情況看起來像斯卡拉僞代碼,我只是想說明這個概念。
感謝您的幫助,我結束了使用Akka的駱駝與終端和演員池的整合,並且我喜歡它:) – parsa
嘿,帕薩,你完全放棄了Scalatra嗎? –
是的,我在這個項目中做過。 – parsa