Introduction of Akka Routing
當產生多個 actor 來處理相同事件時, Akka 提供 Router
的機制,來有效分配 message 給 actor 來完成工作。 在 Akka 中,受 Router
管理的 actor 稱作 Routee
。
Akka 提供以下 routing 的管理方式:
akka.routing.RoundRobinRoutingLogic
akka.routing.RandomRoutingLogic
akka.routing.SmallestMailboxRoutingLogic
akka.routing.BroadcastRoutingLogic
akka.routing.ScatterGatherFirstCompletedRoutingLogic
akka.routing.ConsistentHashingRoutingLogic
參考資料:
實作:
RouterDemo in Sample Code
延用 吃飯、睡覺、打東東 的範列,由 PenguinKing
產生 Penguin
。PenguinManager
擔任 Router 角色,分配工作。Reporter
會透過 PenguinManager
詢問所有的企鵝,共 100 次,每隻企鵝會記錄被問了幾次,並回報給記者。
如何使用 Router
var router = {
val routees = Vector.fill(5) {
val r = context.actorOf(Props[Worker])
context watch r
ActorRefRoutee(r)
}
Router(RoundRobinRoutingLogic(), routees)
}
使用 Router 很簡單,首先將產生的 ActorRef
利用 ActorRefRoutee
,再加入 Router
並設定此 Router
要使用那種管理方式,如上例使用 RoundRobinRoutingLogic
。
使用 Router 時,記得把變數設成 var
,因為當要加入/移除 Actor 時,Akka 會重新產生新的 Router
,此時必須 re-assign 變數。
PenguinManager
:
/**
* 企鵝總管
*/
class PenguinManager extends Actor {
var router = Router(RoundRobinRoutingLogic())
def receive: Actor.Receive = {
case PenguinReady(actor) =>
context watch actor
router = router.addRoutee(actor)
println("manager watch " + actor.path)
case Terminated(actor) =>
println("manager remove " + actor.path)
router = router.removeRoutee(actor)
case Interest =>
router.route(Interest, sender)
case QueryCount =>
router.routees foreach { actor =>
actor.send(QueryCount, sender)
}
case Hit =>
router.route(Hit, sender)
case KillOne =>
router.routees(0).send(PoisonPill, self)
case _ =>
}
}
object PenguinManager {
val props = Props[PenguinManager]
}
如果要進一步監控 actor,可以使用 watch
,如上例 context watch actor
,當被監控 actor 中止時,監控者會收到 Terminated
的訊息,其中會指名那個 actor 已經中止。如下:
case Terminated(actor) =>
println("manager remove " + actor.path)
router = router.removeRoutee(actor)
如果要測試不同的 routing 的方式,則修改 var router = Router(RoundRobinRoutingLogic())
即可。
沒有留言:
張貼留言