У меня есть следующая настройка актеров с использованием актеров Akka (2.10)
A -спаун-> B -спаун-> C
A -sendWork-> B -sendWork-> C
C -sendResults-> A (повторно)
Однако в какой-то момент A замечает, что он должен изменить рабочую нагрузку, отправляемую на B / C, потому что C отправляет большое количество сообщений, которые оказываются бесполезными. Однако в таких ситуациях почтовый ящик C кажется очень переполненным и / или C может быть заблокирован.
Как A может сказать B немедленно выключить C? Потеря состояния и сообщений как B, так и C приемлема, поэтому их можно уничтожить и создать новые.
1 ответ
Если акторы запускаются так, как вы описали, то правильное использование stop
сделает то, что вам нужно. Согласно документам, вызов stop будет:
1) запретить попадание дополнительных сообщений в почтовый ящик (отправлено на мертвую букву)
2) возьмите текущее содержимое почтового ящика и также отправьте его в мертвую рассылку (хотя это основано на имплантации почтового ящика, но дело в том, что они не будут обрабатываться)
Теперь, если актеру нужно будет полностью закончить сообщение, которое он в настоящее время обрабатывает, прежде чем оно будет полностью остановлено, поэтому, если оно "зависло", остановка (или что-то еще в этом отношении) не исправит это, но я не думаю, что это ситуация, которую вы описываете.
Я собрал небольшой образец кода для демонстрации. По сути, A отправляет сообщение B, чтобы начать отправку работы C. B наводняет C некоторой работой, а C отправляет результаты этой работы обратно A. Когда определенное количество ответов будет получено A, он будет инициировать остановку B и C путем остановки B. Когда B полностью остановлен, он затем перезапустит процесс снова, до 2 раз, потому что он останавливается сам. Код выглядит так:
case object StartWork
case class DoWork(i:Int, a:ActorRef)
case class WorkResults(i:Int)
class ActorA extends Actor{
import context._
var responseCount = 0
var restarts = 0
def receive = startingWork
def startingWork:Receive = {
case sw @ StartWork =>
val myb = actorOf(Props[ActorB])
myb ! sw
become(waitingForResponses(myb))
}
def waitingForResponses(myb:ActorRef):Receive = {
case WorkResults(i) =>
println(s"Got back work results: $i")
responseCount += 1
if (responseCount > 200){
println("Got too many responses, terminating children and starting again")
watch(myb)
stop(myb)
become(waitingForDeath)
}
}
def waitingForDeath:Receive = {
case Terminated(ref) =>
restarts += 1
if (restarts <= 2){
println("children terminated, starting work again")
responseCount = 0
become(startingWork)
self ! StartWork
}
else{
println("too many restarts, stopping self")
context.stop(self)
}
}
}
class ActorB extends Actor{
import concurrent.duration._
import context._
var sched:Option[Cancellable] = None
override def postStop = {
println("stopping b")
sched foreach (_.cancel)
}
def receive = starting
def starting:Receive = {
case sw @ StartWork =>
val myc = context.actorOf(Props[ActorC])
sched = Some(context.system.scheduler.schedule(1 second, 1 second, self, "tick"))
become(sendingWork(myc, sender))
}
def sendingWork(myc:ActorRef, a:ActorRef):Receive = {
case "tick" =>
for(j <- 1 until 1000) myc ! DoWork(j, a)
}
}
class ActorC extends Actor{
override def postStop = {
println("stopping c")
}
def receive = {
case DoWork(i, a) =>
a ! WorkResults(i)
}
}
Это немного грубовато по краям, но должно показать, что каскадирование остановки от B до C не позволит C отправлять ответы обратно A, даже если у него все еще есть сообщения в почтовом ящике. Надеюсь, это то, что вы искали.
Похожие вопросы
Новые вопросы
akka
Akka - это инструментарий с открытым исходным кодом и среда выполнения, упрощающая создание параллельных и распределенных приложений на JVM. Он реализует модель актера, известную из Эрланга.