2012-03-05 1 views
21

Я реализовал систему Актера, используя Akka и его API Java UntypedActor. В нем один актер (тип A) запускает других участников (тип B) динамически по требованию, используя getContext().actorOf(...);. Те B-актеры будут делать некоторые вычисления, которые A на самом деле не волнует больше. Но мне интересно: нужно ли очищать тех актеров типа B, когда они закончили? Если да, то как?Akka: Очистка динамически созданных актеров необходима, когда они закончили?

  • Имея актеры B, звоните getContext().stop(getSelf()), когда они закончены?
  • Имея актеры B, звоните getSelf().tell(Actors.poisonPill());, когда они закончены? [это то, что я использую сейчас].
  • Ничего не делая?
  • By ...?

Документы на этом не ясны, или я не обратил на это внимания. У меня есть некоторые базовые знания Scala, но источники Akka - это не совсем начальные вещи ...

ответ

23

Что вы описываете - это одноцелевые актеры, созданные за «запрос» (определенные в контексте A), которые обрабатывают последовательность событий, а затем выполняются, правильно? Это абсолютно нормально, и вы правы закрыть их: если вы этого не сделаете, они будут накапливаться с течением времени, и вы столкнетесь с утечкой памяти. Лучший способ сделать это - это первая из возможностей, которую вы упомянули (самая прямая), но вторая тоже в порядке.

Немного фона: актеры зарегистрированы у их родителей, чтобы быть идентифицируемыми (например, необходимыми в удалении, но и в других местах), и эта регистрация не позволяет им собирать мусор. OTOH, каждый родитель имеет право доступа к созданным им детям, поэтому автоматическое завершение (то есть Akka) не имеет смысла, вместо этого требуется явное закрытие кода пользователя.

+0

http: // stackoverflow.com/вопросы/23066264/can-wrapping-akka-players-in-class-players-cause-memory-leaks <- Связанный вопрос –

-3

Актеры по умолчанию не потребляют много памяти. Если приложение намерено использовать актер b позже, вы можете сохранить их в живых. Если нет, вы можете закрыть их через яд. До тех пор, пока ваши актеры не будут располагать ресурсами, вы должны быть в порядке.

+4

Но, как указал Роланд, актеры не собираются собирать мусор и, следовательно, накапливаются с течением времени => утечка памяти. –

0

В дополнение к ответу Роланда Куна вместо создания нового актера для каждого запроса вы можете создать предопределенный набор участников, которые используют один и тот же диспетчер, или вы можете использовать маршрутизатор, который распространяет запросы в пул участников.

Balancing Pool Router, например, позволяет иметь фиксированный набор актеров определенной доли типа тот же почтовый ящик:

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

Прочитайте документацию по dispatchers и routing для дальнейших деталей.

0

Я профилировал (visualvm) одно из примеров кластерного приложения из документации AKKA, и я вижу уборку мусора, очищающую каждого участника запроса во время каждого GC. Невозможно полностью понять рекомендацию явно убить актера после использования. Моя актерская система и актеры управляются контейнером SPRING IOC, и я использую весеннее продление в прямом эфире-продюсере для создания актеров. «агрегатор» актер получает мусор, собранный на каждом GC, я контролировал # экземпляров в визуальной виртуальной машине.

@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(); 
    } 
} 
Смежные вопросы