引言
Akka是一个自由的世界,actor之间可以互相发送任意类型的消息,但是随着actor数量的增多,如果不加限制地任由actor之间互相通信,很快整个系统将变得复杂且难以管理。
在互联网的世界,将一群节点组成一个内网,不同网络间的通信,需要通过路由器作为中介。路由使消息传递变得有序。
Akka世界中,也有扮演路由器角色的router,通过router可以管理一组routee的创建、通信和销毁。
创建router
可以用两种不同的方式创建router 和 routee:
-
Pool -
routee由router创建,成为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策略,可以通过router的supervisorStrategy来指定。
远端actor
routee不仅可以是本地actor,也可以是远程actor。由于Akka中actor的地址透明性,本地routee和远程routee的创建方式并没有太大区别。
以Pool创建方式举例:
1 | val addresses = Seq( |
示例代码
红包程序中为了模拟大规模并发请求,创建generatorRouter和clientRouter来分发消息给各个红包生成器及客户端。
1 | import akka.actor.{ActorSystem, Props} |