Akka中Router路由机制

360 阅读3分钟

Router基本概念

在Akka中,Router 也是一种 actor 类型,是负责负载均衡和路由的抽象,把消息按照路由规则调度,分配给Routee去运算,用于调度actor任务或进行负载均衡策略

它路由到来的消息到其他的actors,其他那些actors就叫做routees(被路由对象)。

创建方式

有两种方式来创建Router

  1. Actor Group:Routees由外界其它Actor产生(自行创建,自行管理),特点是能实现灵活的Routee构建和监控。

    List<Routee> routees = new ArrayList<>();
    for (int i = 0; i < 5; i++) {
        ActorRef r = getContext().actorOf(Props.create(ArticleParseActor.class));
        getContext().watch(r);
        routees.add(new ActorRefRoutee(r));
    }
    Router router = new Router(new RoundRobinRoutingLogic(), routees);
    
  2. Actor Pool:由Router负责构建所有的Routee,routee作为子actor,并在该子actor终止时将它从Router中移除。

    ActorSystem actorSystem = ActorSystem.create("lpSys");
            ActorRef routerActorRef = actorSystem.actorOf(
                    Props.create(ArticleParseActor.class).withRouter(new RoundRobinPool(8)), //RoundRobinPool:表示依次往复循环发送
                    "lpRouterActor");
    

路由策略

在前面我们使用了 RoundRobinPool/RoundRobinGroup, 用于指定 Router 将消息发送给各 Actor 的顺序。Akka 内置了一些路由策略:

路由策略功能
Round Robin依次向 Pool/Group 中的各个节点发送消息,循环往复。Random——随机向各个节点发送消息。
Smallest Mailbox向当前包含消息数量最少的 Actor 发送消息。由于远程 Actor 的邮箱大小未知,因此假设它们的队列中已经有消息在排队。所以会优先将消息发送给空闲的本地 Actor。
Scatter Gather向 Group/Pool 中的所有 Actor 都发送消息,使用接收到的第一个响应,丢弃之后收到的任何其他响应。如果需要确保能够尽快收到一个响应,那么可以使用 scatter/gather。
Tail Chopping和Scatter/Gather类似, 但是Router并不是一次性向 Group/Pool中的所有 Actor 都发送一条消息,而是每向一个 Actor 发送消息后等待一小段时间。有着和Scatter/Gather 类似的优点,但是相较而言有可能可以减少网络负载。
Consistent Hashing给 Router 提供一个 key,Router 根据这个 key 生成哈希值。使用这个哈希值来决定给哪个节点发送数据。想要将特定的数据发送到特定的目标位置时,就可以使用哈希。在下章中,我们将讨论更多有关一致性哈希的问题。
BalancingPoolBalancingPool 这个路由策略有点特殊。只可以用于本地 Actor。多个 Actor 共享同一个邮箱,一有空闲就处理邮箱中的任务。这种策略可以确保所有Actor 都处于繁忙状态。对于本地集群来说,经常会优先选择这个路由策略。

向routees发送消息

router.tell(new akka.routing.Broadcast(msg));

监督Pool中的routees

如果使用 Pool 的方式创建 Router,由 Router 负责创建 Actor,那么这些路由对象会成为 Router 的子节点。创建 Router 时,可以给 Router 提供一个自定义的监督策略,调用 withSupervisorStrategy 方法指定 Router 对 Pool 中路由对象的监督策略。

ActorRefworkerRouter = system.actorOf(  
			Props.create(ArticleParseActor.class)  
					 .withRouter(new RoundRobinPool(8)
					 .withSupervisorStrategy(strategy))
			);

参考文献

  • 《Akka入门与实践》

关注公众号回复Akka领取《Akka入门与实践》书籍 关注公众号 数据工匠记 ,专注于大数据领域离线、实时技术干货定期分享!个人网站 www.lllpan.top 在这里插入图片描述