Акка: Очистка динамически созданных актеров необходима, когда они закончили?
Я реализовал систему Actor с использованием Akka и ее Java API UntypedActor. В нем один актер (тип A) запускает других актеров (тип B) динамически по требованию, используя getContext().actorOf(...);
, Те актеры B сделают некоторые вычисления, о которых A больше не заботится. Но мне интересно: нужно ли убирать тех актеров типа В, когда они закончат? Если так, то как?
- Принимая B актеров звонить
getContext().stop(getSelf())
когда они закончили? - Принимая B актеров звонить
getSelf().tell(Actors.poisonPill());
когда они закончили? [это то, что я использую сейчас]. - Ничего не делая?
- От...?
Документы не ясны по этому поводу, или я упустил это. У меня есть некоторые базовые знания о Scala, но источники Akka не совсем начальные материалы...
4 ответа
То, что вы описываете, - это актеры специального назначения, созданные по "запросу" (определенные в контексте A), которые обрабатывают последовательность событий и затем выполняются, верно? Это абсолютно нормально, и вы правы, чтобы закрыть их: если вы этого не сделаете, они будут накапливаться со временем, и вы столкнетесь с утечкой памяти. Лучший способ сделать это - первая из упомянутых вами возможностей (самая прямая), но вторая тоже подойдет.
Немного предыстории: актеры регистрируются в своих родителях, чтобы их можно было идентифицировать (например, необходимо для удаленного взаимодействия, но также и в других местах), и эта регистрация не позволяет собирать мусор. OTOH, каждый родитель имеет право доступа к созданным им дочерним элементам, поэтому автоматическое завершение (например, Akka) не имеет смысла, вместо этого требуется явное завершение работы в пользовательском коде.
Я профилировал (visualvm) одно из примеров кластерного приложения из документации AKKA, и я вижу, что сборка мусора очищает участников каждого запроса во время каждого GC. Невозможно полностью понять рекомендацию явно убить актера после использования. Моя система актеров и актеры управляются контейнером SPRING IOC, и я использую весеннее расширение в непосредственном актере-продюсере для создания актеров. Актор "агрегатора" собирает мусор на каждом ГХ, я контролировал количество экземпляров в визуальной ВМ.
@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();
}
}
В дополнение к ответу Ролана Куна вместо создания нового субъекта для каждого запроса вы можете создать предварительно определенный набор участников, совместно использующих один и тот же диспетчер, или использовать маршрутизатор, который распределяет запросы по пулу субъектов.
Например, маршрутизатор балансировочного пула позволяет иметь фиксированный набор актеров определенного типа, использующих один и тот же почтовый ящик:
akka.actor.deployment {
/parent/router9 {
router = balancing-pool
nr-of-instances = 5
}
}
Прочитайте документацию о диспетчерах и маршрутизации для получения дополнительной информации.
Актеры по умолчанию не занимают много памяти. Если приложение намеревается использовать актера b позже, вы можете сохранить их. Если нет, вы можете отключить их с помощью яда. Пока ваши актеры не держат ресурсы, уйти с актера должно быть хорошо.