我有一个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();
}
}
在第一个(最快)结果出现之后实施丢弃消息逻辑的最佳模式是什么?
答案 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();
}
}
上述方法有两个假设:
CalculationRequest
和CalculationResult
类中都有一个请求ID(在此示例中,ID为Long
;请使用适当的内容。)更简单的解决方案是不使用路由器,在这种情况下,CalculationSupervisor
不需要为同一请求协调多个结果。由于您丢弃了每个请求的最早结果,因此首先使用路由器是没有意义的。