Akka广播:得到第一个回复并丢弃其他人

时间:2017-11-11 16:45:04

标签: java akka broadcast

我有一个CalculationSupervisor演员,有一个工人池 每次我需要进行一些计算时,CalculationSupervisor使用路由器向工作人员广播CalculationRequest

我需要获得最快计算的结果并忽略其他结果。

CalculationSupervisor如下所示:

public class CalculationSupervisor extends AbstractActor {

    private Router router = new Router(new RoundRobinRoutingLogic());

    public static Props props() {
        return Props.create(CalculationSupervisor.class, CalculationSupervisor::new);
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(RegisterWorker.class, registration -> {
                    final String workerName = registration.name();
                    final ActorRef worker = 
                        context().actorOf(Worker.props(workerName), workerName);
                    router = router.addRoutee(worker);
                })
                .match(CalculationRequest.class, (request) -> {
                    router.route(new Broadcast(request), self());
                })
                .match(CalculationResult.class, (result) -> {
                    // process only the first (the fastest) result
                })
                .build();
    }
}

在第一个(最快)结果出现之后实施丢弃消息逻辑的最佳模式是什么?

1 个答案:

答案 0 :(得分:0)

如果您的主管正在处理多个请求,一个简单的方法是保留一个Map,其中包含请求ID对和请求的响应数。只有在处理时,特定请求ID的回复数为零,主管才会检查此映射并处理回复。此外,为了防止地图无限增长,如果结果数等于池大小,主管将从地图中删除条目:

public class CalculationSupervisor extends AbstractActor {
    ...
    private int poolSize = 0;
    private Map<Long, Integer> numReplies = new HashMap<>();

    @Override
    public Receive createReceive() {
        return receiveBuilder()
            .match(RegisterWorker.class, registration -> {
                ...
                poolSize = poolSize + 1;
            })
            .match(CalculationRequest.class, request -> {
                numReplies.putIfAbsent(request.getId(), 0);
                router.route(new Broadcast(request), self());
            })
            .match(CalculationResult.class, result -> {
                Long requestId = result.getRequestId();
                if (numReplies.contains(requestId)) {
                    int num = numReplies.get(requestId);
                    if (num == 0) {
                        // process only the first (the fastest) result
                        ...
                        numReplies.put(requestId, 1);
                    } else {
                        if (num + 1 == poolSize)
                            numReplies.remove(requestId);
                        else
                            numReplies.put(requestId, num + 1);
                    }
                }
            })
            .build();
    }
}

上述方法有两个假设:

  1. CalculationRequestCalculationResult类中都有一个请求ID(在此示例中,ID为Long;请使用适当的内容。)
  2. 在发送请求之前,路由器已在主管处注册。
  3. 更简单的解决方案是不使用路由器,在这种情况下,CalculationSupervisor不需要为同一请求协调多个结果。由于您丢弃了每个请求的最早结果,因此首先使用路由器是没有意义的。