2012-03-05 3 views
21

Akka와 Java API UntypedActor를 사용하여 Actor 시스템을 구현했습니다. 이 중 하나의 액터 (유형 A)는 getContext().actorOf(...);을 사용하여 필요에 따라 다른 액터 (유형 B)를 동적으로 시작합니다. 그 B 액터는 A가 더 이상 신경 쓰지 않는 계산을 할 것입니다. 하지만 궁금한 점이 있습니다. B 유형의 배우를 정리해야 할 필요가 있습니까? 그렇다면 어떻게?Akka : 동적으로 생성 된 액터의 정리가 끝나면 정리가 필요합니까?

  • B 액자가 완료되면 getContext().stop(getSelf())을 호출하게되면 어떻게됩니까?
  • B 액자가 완료되면 getSelf().tell(Actors.poisonPill());으로 전화하면됩니까? [이것은 지금 내가 사용하는 것입니다].
  • 아무것도하지 않음으로써?
  • 으로 ...?

문서가 명확하지 않거나 간과했습니다. 나는 스칼라의 몇 가지 기본적인 지식을 가지고 있지만, Akka 소스는 ​​기본적으로

답변

23

당신이 설명하는 것은 "요청"(A의 컨텍스트에서 정의 됨)마다 생성 된 단일 목적 액터로, 일련의 이벤트를 처리 한 다음 완료됩니다. 그것은 절대적으로 좋으며, 당신은 그것들을 폐쇄하는 것이 옳습니다. 그렇지 않으면, 시간이 지남에 누적 될 것이고 당신은 기억 누출에 빠지게 될 것입니다. 이를 수행하는 가장 좋은 방법은 가장 직접적으로 언급 할 수있는 가능성의 첫 번째 방법이지만 두 번째 방법은 괜찮습니다.

배경 설명 : 액터 식별 가능한되기 위해 (예를 들어 다른 장소에서도 원격에서 필요하지만)에서 상위 내에 등록되며,이 등록은 가비지 수집되는 것을 유지한다. OTOH를 사용하면 각 부모는 자신이 만든 자녀를 액세스 할 수있는 권한을 가지므로 자동 종료 (예 : Akka)가 의미가 없으며 대신 사용자 코드에서 명시적인 종료가 필요합니다.

+0

http : // stackoverflow.com/questions/23066264/can-wrapping-akka-actors-in-class-actors에 의한 메모리 누수 <- 관련 질문 –

-3

배우가 많은 메모리를 소모하지 않습니다 ... 정확히 엔트리 레벨 물건이 아니다. 응용 프로그램에서 나중에 배우 b를 사용하려는 경우 해당 활동자를 유지할 수 있습니다. 그렇지 않다면, 독약을 통해 그들을 닫을 수 있습니다. 배우가 리소스를 보유하지 않는 한 배우를 남겨 두는 것이 좋습니다.

+4

그러나 Roland가 지적했듯이 액터는 가비지 수집되지 않으므로 시간이 지남에 따라 누적됩니다. –

0

모든 요청에 ​​대해 새 액터를 만드는 대신 Roland Kuhn의 답변 외에도 동일한 디스패처를 공유하는 미리 정의 된 액터 세트를 만들거나 요청자를 액터 풀에 배포하는 라우터를 사용할 수 있습니다.

akka.actor.deployment { 
    /parent/router9 { 
    router = balancing-pool 
    nr-of-instances = 5 
    } 
} 

더 세부 사항에 대한 dispatchersrouting에 설명서를 읽기 :

Balancing Pool Router 예를 들어, 특정 유형의 공유의 배우 같은 사서함의 고정 세트를 가지고 있습니다.

0

저는 AKKA 문서의 샘플 클러스터 응용 프로그램 중 하나를 프로파일 링 (visualvm)하고 모든 GC 동안 요청 별 액터를 정리하는 가비지 콜렉션을 봅니다. 사용 후 명시 적으로 배우를 죽이는 권장 사항을 완전히 이해할 수 없습니다. 내 액터 시스템과 액터는 SPRING IOC 컨테이너에 의해 관리되며 저는 스프링 확장 직접 직접 액터 프로듀서를 사용하여 액터를 만듭니다. "어 그리 게이터"액터가 모든 GC에서 가비지 수집 중입니다. 시각적 VM의 인스턴스 수를 모니터했습니다.

@Component 
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) 
public class StatsService extends AbstractActor { 

    private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this); 

    @Autowired 
    private ActorSystem actorSystem; 

    private ActorRef workerRouter; 

    @Override 
    public void preStart() throws Exception { 
     System.out.println("Creating Router" + this.getClass().getCanonicalName()); 
     workerRouter = getContext().actorOf(SPRING_PRO.get(actorSystem) 
      .props("statsWorker").withRouter(new FromConfig()), "workerRouter"); 
     super.preStart(); 
    } 

    @Override 
    public Receive createReceive() { 
     return receiveBuilder() 
      .match(StatsJob.class, job -> !job.getText().isEmpty(), job -> { 
       final String[] words = job.getText().split(" "); 
       final ActorRef replyTo = sender(); 
       final ActorRef aggregator = getContext().actorOf(SPRING_PRO.get(actorSystem) 
        .props("statsAggregator", words.length, replyTo)); 

       for (final String word : words) { 
        workerRouter.tell(new ConsistentHashableEnvelope(word, word), 
         aggregator); 
       } 
      }) 
      .build(); 
    } 
}