Akka具有分布式、集群、微服务等特点,可以快速构建高可用、高性能的分布式应用。多个Actor之间消息传递,可以使用tell、ask、forward等简单方式,但是当一组Actor需要进行有规律的消息传递时,就显得稍微复杂。Akka路由组件,就是为了解决我们复杂的消息传递,例如广播、轮询、随机等,有两种实现方式:配置和代码创建。
什么是路由
路由就是一组消息按照指定规则被分配到各个地方。Akka中使用路由,需要依赖两个对象Router和Routee。Router表示路由器,消息会进入该路由器然后转发出去,相当于消息中转站。Routee表示路由目标,最终消息会被分配到这里。上面所说的指定规则就是路由策略,表明我们应该怎样分配这些消息。
路由使用
使用路由组件,我们需要先创建路由目标Actor,然后将它们包装成Routee对象(表明这些Actor是路由目标),之后创建Router对象,按照路由策略将消息转发给路由目标Actor。如下:
创建路由目标Actor:
/**
* @author php
* @date 2018/11/18
* 路由目标(用于接受路由器转发的消息)
*/
public class FirstRoutee extends AbstractActor {
@Override
public Receive createReceive() {
return receiveBuilder().matchAny(o -> {
//打印当前actor信息,便于我们分析路由规则
System.out.println(getSelf() + "-->" + o);
}).build();
}
}
创建路由器Actor:
public class FirstRouter extends AbstractActor {
private Router router;
public static void main(String[] args) {
ActorSystem system = ActorSystem.create("system");
ActorRef router = system.actorOf(Props.create(FirstRouter.class), "router");
router.tell("MessageOne",ActorRef.noSender());
router.tell("MessageTwo",ActorRef.noSender());
router.tell("MessageThree",ActorRef.noSender());
}
/**
* 生命周期方法
* 当该Actor启动时,先调用该方法,
* 我们在这里初始化Routee列表
*
* @throws Exception exception
*/
@Override
public void preStart() throws Exception {
List<Routee> routeeList = new ArrayList<>();
for (int i = 0; i < 2; i++) {
ActorRef ref = getContext().actorOf(Props.create(FirstRoutee.class), "routee" + i);
//监控子actor
getContext().watch(ref);
//创建路由目标,并添加到集合中去
routeeList.add(new ActorRefRoutee(ref));
}
//创建轮询路由器RoundRobinRoutingLogic
router = new Router(new RoundRobinRoutingLogic(), routeeList);
}
@Override
public Receive createReceive() {
return receiveBuilder().match(Terminated.class, t -> {
//当子Actor停止,从路由列表中移除
router.removeRoutee(t.actor());
}).matchAny(o -> {
//转发消息给路由目标
router.route(o, getSender());
}).build();
}
}
上述我们创建了路由目标类FirstRoutee和