2011-07-10 41 views
4

我的目標是爲我的小部件構建高度併發的後端。我目前正在將後端展示爲一個Web服務,該服務接收運行特定窗口小部件(使用Scalatra)的請求,從數據庫中獲取窗口小部件的代碼並將其運行在一個actor中(使用Akka),然後使用結果進行回覆。所以,想象我在做這樣的事情:使用Akka和Scalatra

get("/run:id") { 
    ... 
    val actor = Actor.actorOf("...").start 
    val result = actor !! (("Run",id), 10000) 
    ... 
} 

現在,我相信這是不是最好的併發解決方案,我應該以某種方式結合起來監聽請求,並以一個演員的實施運行的微件。你如何設計這個最大併發性?謝謝。

回答

5

您可以在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() 
    } 
    } 
} 

請不要考慮上面的代碼,如發生這種情況看起來像斯卡拉僞代碼,我只是想說明這個概念。

+1

感謝您的幫助,我結束了使用Akka的駱駝與終端和演員池的整合,並且我喜歡它:) – parsa

+0

嘿,帕薩,你完全放棄了Scalatra嗎? –

+0

是的,我在這個項目中做過。 – parsa