Akka in Scala Part 6 - Router

引言

Akka是一个自由的世界,actor之间可以互相发送任意类型的消息,但是随着actor数量的增多,如果不加限制地任由actor之间互相通信,很快整个系统将变得复杂且难以管理。

在互联网的世界,将一群节点组成一个内网,不同网络间的通信,需要通过路由器作为中介。路由使消息传递变得有序。

Akka世界中,也有扮演路由器角色的router,通过router可以管理一组routee的创建、通信和销毁。

创建router

可以用两种不同的方式创建routerroutee

  • Pool - routeerouter创建,成为router的子actor, 由router管理其生命周期。优势在于:

    • Router来定义监护策略。
    • routee的路径和名字由系统自动生成。
    • 代码示例:

      1
      val router: ActorRef = context.actorOf(RoundRobinPool(5).props(Props[Worker]), "router")
  • Group - routee是独立的actor, 在router创建时,将其路径传递给router的配置,router并不负责管理routee的生命周期。优势在于:

    • routee的创建更加灵活,不受router的限制。
    • routee的监护更加灵活,因为每个routee由它自己的父actor来决定监护策略。
    • 代码示例:

      1
      val router: ActorRef = context.actorOf(RoundRobinGroup(paths).props(), "router")

路由策略

Akka提供了多种形式的路由策略,常用的有:

- akka.routing.RoundRobinRoutingLogic
    * 轮盘路由策略,依次选取各个`routee`来处理消息。
- akka.routing.RandomRoutingLogic
    * 随机路由策略,随机选取`routee`来处理消息。
- akka.routing.SmallestMailboxRoutingLogic
    * 选取当前收件箱size最小的`routee`来处理消息,这种方式具有更好的负载均衡性。
- akka.routing.BroadcastRoutingLogic
    * 将消息广播给所有的`routee`。

监护策略

对于用Pool方式创建的router,默认的监护策略是escalate,当routee抛出异常时,将错误向上传递给router, router继续向上传递给它的父actor,由父actor来决定如何恢复。

如果要替换默认的escalate策略,可以通过routersupervisorStrategy来指定。

远端actor

routee不仅可以是本地actor,也可以是远程actor。由于Akkaactor的地址透明性,本地routee和远程routee的创建方式并没有太大区别。

Pool创建方式举例:

1
2
3
4
5
val addresses = Seq(
Address("akka.tcp", "remotesys", "otherhost", 1234),
AddressFromURIString("akka.tcp://othersys@anotherhost:1234"))
val routerRemote = system.actorOf(
RemoteRouterConfig(RoundRobinPool(5), addresses).props(Props[Echo]))

示例代码

红包程序中为了模拟大规模并发请求,创建generatorRouterclientRouter来分发消息给各个红包生成器及客户端。

1
2
3
4
5
import akka.actor.{ActorSystem, Props}
import akka.routing.RoundRobinPool

val generatorRouter = system.actorOf(RoundRobinPool(100, supervisorStrategy = ResumeSupervisor()).props(Props[RedPacketGenerator]), "generatorRouter")
val clientRouter = system.actorOf(RoundRobinPool(100).props(Props(classOf[RedPacketClient], generatorRouter)), "clientRouter")