技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

Akkaのrouterを調べる

とりあえず内容はこれ

http://doc.akka.io/docs/akka/2.2-M3/scala/routing.html

A Router is an actor that receives messages and efficiently routes them to other actors, known as its routees.

そのままですよね。Actorのインスタンスが複数ある時に、その振り分けを行う actor のこと。

For example, the following code and configuration snippets show how to create a round-robin router that forwards messages to five ExampleActor routees. The routees will be created as the router's children.
たとえば、下記コードと設定を行うことで、Round-robin router を作成することができ、5個の ExampleActor の routees インスタンスに振り分けられる。routees はこのとき、router の子として作成される。


akka.actor.deployment {
  /myrouter1 {
    router = round-robin
    nr-of-instances = 5
  }
}

val router = system.actorOf(Props[ExampleActor].withRouter(FromConfig()),
  "myrouter1")

デフォルトで存在してるルータ一覧。

  • akka.routing.RoundRobinRouter
  • akka.routing.RandomRouter
  • akka.routing.SmallestMailboxRouter
  • akka.routing.BroadcastRouter
  • akka.routing.ScatterGatherFirstCompletedRouter
  • akka.routing.ConsistentHashingRouter

なんてルータがある。公式に使い方が乗ってる。特性はドキュメント読んで。

「Handling for Special Messages」のあたり。

  • Broadcast Messages : 言うまでもなさそう
  • PoisonPill Messages : 受け取ったアクターを停止させる命令メッセージらしい。受け取りは router actor のみでrouteesには影響なしなんだそうな。もっとも router が落ちると傘下の routees も当然落ちる
  • Kill Messages : 言うまでもなさそう。気になる場合はこれ

Custom Router

これこれ、ここ調べたかった。

You can create your own router should you not find any of the ones provided by Akka sufficient for your needs. In order to roll your own router you have to fulfill certain criteria which are explained in this section.
Akka の提供する router にニーズを満たすものが無い場合、router を自作することもできる。このとき、定義するルータはこのセクションで説明する一定基準を満たす必要がある。

Before creating your own router you should consider whether a normal actor with router-like behavior might do the job just as well as a full-blown router. As explained above, the primary benefit of routers over normal actors is their higher performance. But they are somewhat more complicated to write than normal actors. Therefore if lower maximum throughput is acceptable in your application you may wish to stick with traditional actors. This section, however, assumes that you wish to get maximum performance and so demonstrates how you can create your own router.
router を自作する前に、通常アクターの router っぽい動作と、本格的なルータのどっちが必要なのか考察すべきです。上記で説明しているように、通常アクター上のルータの利点は、その高い性能にあります。もっともそれを書くのは通常のアクターよりも複雑です。要求性能がそんなでも無いのであれば、伝統的なアクターっぽくしたい場合があります。この章では、最大の性能を要求している前提で作り方を紹介します。

げー序文読むだけで悩むなぁ(;´∀`)
と思いましたが、サンプルはそんなでもなかった。

case object DemocratVote
case object DemocratCountResult
case object RepublicanVote
case object RepublicanCountResult
 
class DemocratActor extends Actor {
  var counter = 0
 
  def receive = {
    case DemocratVote        ⇒ counter += 1
    case DemocratCountResult ⇒ sender ! counter
  }
}
 
class RepublicanActor extends Actor {
  var counter = 0
 
  def receive = {
    case RepublicanVote        ⇒ counter += 1
    case RepublicanCountResult ⇒ sender ! counter
  }
}
 
case class VoteCountRouter() extends RouterConfig {
 
  def routerDispatcher: String = Dispatchers.DefaultDispatcherId
  def supervisorStrategy: SupervisorStrategy = SupervisorStrategy.defaultStrategy
 
  def createRoute(routeeProvider: RouteeProvider): Route = {
    val democratActor =
      routeeProvider.context.actorOf(Props(new DemocratActor()), "d")
    val republicanActor =
      routeeProvider.context.actorOf(Props(new RepublicanActor()), "r")
    val routees = Vector[ActorRef](democratActor, republicanActor)
 
    routeeProvider.registerRoutees(routees)
 
    {
      case (sender, message) ⇒
        message match {
          case DemocratVote | DemocratCountResult ⇒
            List(Destination(sender, democratActor))
          case RepublicanVote | RepublicanCountResult ⇒
            List(Destination(sender, republicanActor))
        }
    }
  }
}

メッセージの型によって送り先Actorを振り分けする処理という風に見える。