4

私の目標は、ウィジェットの並行性の高いバックエンドを構築することです。私は現在、バックエンドをWebサービスとして公開しています。このサービスは、特定のウィジェットを実行する要求を受け取り(Scalatraを使用)、DBからウィジェットのコードをフェッチし、アクターで実行し(Akkaを使用)、結果を返信します。だから私が次のようなことをしていると想像してください:

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

これは最善の並行ソリューションではないと思います。リクエストのリッスンとウィジェットの実行を1つのアクター実装で組み合わせる必要があります。最大の同時実行性のためにこれをどのように設計しますか?ありがとう。

4

1 に答える 1

5

akka ブート ファイルまたは独自の ServletContextListener でアクターを開始して、サーブレットに関連付けることなくアクターを開始することができます。次に、akka レジストリでそれらを探すことができます。

Actor.registry.actorFor[MyActor] foreach { _ !! (("Run",id), 10000) }

それを除けば、現時点では akka と scalatra の実際の統合はありません。したがって、これまでにできる最善の方法は、多数のアクターへのブロッキング リクエストを使用することです。

よくわかりませんが、リクエストごとにアクターを生成する必要はなく、それらのリクエストを送信できるウィジェット アクターのプールを用意する必要があります。スーパーバイザー階層を使用すると、プールが大きすぎたり小さすぎたりする場合に、スーパーバイザーを使用してプールのサイズを変更できます。

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()
    } 
  }
}

上記のコードは、たまたま scala のように見える疑似コードと見なしてください。概念を説明したかっただけです。

于 2011-07-10T16:39:15.313 に答える