2016-09-13 2 views
1

У меня есть два актера. Каждый актер находится в другой системе Actor. Первые тайники ActorRef секунды. Первый актер делает:Akka - ActorRef.tell() занимает несколько минут, чтобы доставить сообщение

actorRef.tell(msg, self()) 

и посылает сообщение на второй актер, который делает некоторую обработку и ответы с

getSender().tell(reply, self()) 

Проблема: Начальный РАССКАЗАТЬ() от первого до второго актера иногда занимает 1 -3 минуты (!), Чтобы доставить сообщение.

Других сообщений, отправленных в Akka, кроме этого, означает, что почтовые ящики пустые - система обслуживает один запрос.

деталь системы:

Приложение имеет 500 запланированных актер, что опрос Amazon SQS с просьбой (SQS пуст) каждые 30 секунд (блокирующие). У него есть еще 330 актеров, которые ничего не делают в моем сценарии. Все участники настроены с диспетчером по умолчанию Akka.

Коробка представляет собой экземпляр Amazon EC2 с 2 ядрами и 8-гигабайтной ОЗУ. Использование ЦП и ОЗУ составляет < 5%. JVM имеет около 1000 потоков.

Первоначальная догадка - голодание процессора и переключение контекста из слишком большого количества потоков. НО не воспроизводится локально на моей машине i7 с четырьмя ядрами, даже имея x10 количество участников, которое использует 75% доступной ОЗУ.

Как я могу найти причину этой проблемы? Можно ли профилировать инфраструктуру Akka, чтобы увидеть, что принимает это сообщение, чтобы тратить столько времени на переезд от одного актора к другому?

+0

Я бы использовал профайлер типа 'YourKit' или что-то более простое, чтобы взять дамп потока и понять, сколько у вас потоков, и если все они заблокированы. Если ресурсов нет, ваш актер не сможет отправить сообщение. Кроме того, я не уверен в вашем случае использования, но я бы рекомендовал решение, в котором вам не нужно блокировать потоки. – hveiga

ответ

0

Вероятным источником этой проблемы было переключение контекста из слишком большого количества потоков. Чтобы исправить это следующая конфигурация была добавлена:

actor { 
default-dispatcher { 
executor = "fork-join-executor" 
fork-join-executor 
{ parallelism-min = 8 parallelism-factor = 12.0 parallelism-max = 64 task-peeking-mode = "FIFO" } 
} 
} 

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

Смежные вопросы