Как Akka Futures и Supervisor Strategies справляются с неудачами
Акка Ява здесь. Я только что прочитал документы Akka по шаблону "спросить", используя фьючерсы, и не понимаю, как работают несколько вещей, в отношении сценариев, когда стратегии супервизора (решатели) и обратные вызовы сбоев являются частью картины.
Родитель спрашивает ребенка
Скажем, у меня есть два актера, Fizz
а также Buzz
, где Fizz
является родителем / создателем Buzz
, Так как Fizz
является Buzz
родитель, у него есть SupervisorStrategy
за Buzz
который обрабатывает свои неудачи:
// Groovy pseudo-code
class Fizz extends UntypedActor {
ActorRef buzz
// Contstructor omitted for brevity, but Buzz is the child of
// Fizz.
@Override
void onReceive(Object message) {
if(message instanceof FizzRequest) {
FizzRequest fReq = message as FizzRequest
// Exceptions thrown here (inside of Buzz) will be
// handled by Fizz’s supervisor strategy.
Future<BuzzData> bDataFut = Patterns.ask(buzz,
fReq.buzzRequest, 500)
bDataFut.onComplete(new GetBuzzDataCallback())
// etc.
} else {
unhandled(message)
}
}
@Override
SupervisorStrategy supervisorStrategy() {
new FizzSupervisorStrategy()
}
}
class Buzz extends UntypedActor {
// …etc.
}
class FizzDecider extends Function<Throwable,Directive> {
@Override
Directive apply(Throwable throwable) {
if(throwable instanceof BuzzIsAngryException) {
return SupervisorStrategy.restart()
}
SupervisorStrategy.stop()
}
}
class FizzSupervisorStrategy extends OneForOneStrategy {
FizzSupervisorStrategy() {
super(true, new FizzDecider())
}
}
class GetBuzzDataCallback extends OnComplete<BuzzData> {
@Override
void onComplete(Throwable failure, BuzzData bData) {
if(failure != null) {
// If Buzz is the child of Fizz, does this code execute, or
// just the FizzDecider above? Or both? I’m so confused!
} else {
// Handle success. Likely use an ‘Inbox’ to send
// ‘bData’ back to Fizz.
}
}
}
Иногда, Fizz
нужно спросить Buzz
для некоторых данных. Когда это происходит, может быть один из трех результатов:
Buzz
возвращается успешно и предоставляетGetBuzzDataCallback
сbData
; или жеBuzz
бросаетBuzzIsAngryException
; или жеBuzz
выдает другое исключение / ошибку
Мне интересно, что происходит с последними двумя случаями:
- Кто уведомлен об исключении, в каком порядке и как? Другими словами, это
GetBuzzDataCallback
отправил исключение как егоThrowable failure
аргумент? Или этоFizzFailureDecider
вызывается? Или и то, и другое (кажется немного избыточным и усложняющим, если и обратный вызов, и стратегия решающего / супервизорного управления передают ошибку)?
Родитель спрашивает не ребенка
Тот же сценарий, что и выше, только сейчас Fizz
не является родителем / создателем Buzz
, В этом случае я могу просто предположить, что GetBuzzDataCallback
отправлено исключение (как его Throwable failure
аргумент)?
Я предполагаю, что корень моего (их) вопроса (ов) заключается в следующем: когда задействована стратегия супервизора и будущий обратный вызов, кто получает уведомление, когда выдается дочернее исключение, и в каком порядке? Как я упоминал выше, для меня было бы очень запутанным, если оба получат ошибку / исключение, потому что тогда у вас может быть стратегия супервизора, пытающаяся перезапустить Buzz
в то время как обратный вызов пытается сделать что-то другое (возможно, конфликтующее) с исключением.
Обратите внимание: хотя это определенно не является обязательным требованием, я был бы очень признателен, если бы любые предоставленные фрагменты кода были на Java, а не на Scala (для меня Scala выглядит иероглифами)!
1 ответ
То, что делает запрос, - это, в основном, запуск временного субъекта, который будет отправителем сообщения, чтобы, когда получатель отвечает, он оказался в этом временном субъекте. Временный актер создает Promise
и отдает Future
для звонящего. Если ответ приходит до истечения указанного времени, временный субъект завершает Promise
с успешным результатом.
Наблюдение всегда происходит у актеров, и, поскольку запрос реализован с использованием актера, в этом взаимодействии нет ничего отличного от случайного другого актера, отправляющего ему сообщение, которое могло бы заставить надзор работать иначе.
В вашем случае исключение возникнет у родительского субъекта, чтобы он мог контролировать ребенка. Затем, если вы не отправите ответное сообщение, вызванное этой ошибкой, истечет время ожидания ask
-актор провалит будущее с AskTimeoutException
,
Таким образом, так как этот сбой может достичь родителя двумя способами, обычно не стоит использовать шаблон запроса с родительским взаимодействием.