2017-11-11 8 views
0

나는 근로자 수영장이있는 CalculationSupervisor 배우가 있습니다.
계산을 할 때마다 CalculationSupervisor은 라우터를 사용하여 근로자에게 CalculationRequest을 브로드 캐스팅합니다.Akka 방송 : 첫 번째 답장을 받고 다른 사람을 버리십시오.

가장 빠른 계산 결과를 얻고 다른 결과는 무시해야합니다.

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(); 
    } 
} 

첫 번째 (가장 빠른)이 올 및 결과 들어오는 메시지를 폐기의 로직을 구현하는 가장 좋은 패턴은 무엇인가 : 다음과 같이

CalculationSupervisor 보인다?

답변

0

관리자가 여러 요청을 처리하는 경우 간단한 방법은 요청 ID 쌍과 요청에 대해 수신 된 응답 수를 보유하는 Map을 유지하는 것입니다. 감독자는이 맵을 검사하고 처리시 해당 특정 요청 ID에 대한 회신 수가 0 인 경우에만 회신을 처리합니다.

  1. :

    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(); 
        } 
    } 
    

    위의 접근 방식이 가정이 있습니다 결과의 수를 풀 크기와 동일한 경우 또한, 무기한 성장에서지도를 방지하기 위해 관리자는지도에서 항목을 삭제 요청 ID는 CalculationRequestCalculationResult 클래스에서 사용할 수 있습니다 (이 예에서는 ID가 Long이며 적절한 경우 사용하십시오).

  2. 요청을 보내기 전에 경로가 감독자에게 등록됩니다.

더 간단한 해결 방법은 라우터를 사용하지 않는 것입니다.이 경우 라우터 CalculationSupervisor은 동일한 요청에 대해 여러 결과를 조정할 필요가 없습니다. 모든 요청에 ​​대해 가장 초기 결과를 제외하고 모두 폐기하기 때문에 처음부터 라우터를 사용하는 것은 이치에 맞지 않습니다.

+0

CalculationSupervisor에 대한 요청이 많아서 모두 처리하고 싶습니다. 귀하의 접근 방식에서 들어오는 CalculationRequest에 대한 CalculationResult를 얻으면 다른 요청에 대한 처리 결과가 중지됩니다. 사용자의 솔루션은 계산 요구 사항 식별자와 해당 상태를 저장하는 맵을 사용하여 확장 할 수 있습니다. 이것은 내 원래 생각이지만, 더 우아한 해결책을 찾고 싶습니다 :) –