Как 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 для некоторых данных. Когда это происходит, может быть один из трех результатов:

  1. Buzz возвращается успешно и предоставляет GetBuzzDataCallback с bData; или же
  2. Buzz бросает BuzzIsAngryException; или же
  3. Buzz выдает другое исключение / ошибку

Мне интересно, что происходит с последними двумя случаями:

  • Кто уведомлен об исключении, в каком порядке и как? Другими словами, это GetBuzzDataCallback отправил исключение как его Throwable failure аргумент? Или это FizzFailureDecider вызывается? Или и то, и другое (кажется немного избыточным и усложняющим, если и обратный вызов, и стратегия решающего / супервизорного управления передают ошибку)?

Родитель спрашивает не ребенка

Тот же сценарий, что и выше, только сейчас Fizz не является родителем / создателем Buzz, В этом случае я могу просто предположить, что GetBuzzDataCallback отправлено исключение (как его Throwable failure аргумент)?

Я предполагаю, что корень моего (их) вопроса (ов) заключается в следующем: когда задействована стратегия супервизора и будущий обратный вызов, кто получает уведомление, когда выдается дочернее исключение, и в каком порядке? Как я упоминал выше, для меня было бы очень запутанным, если оба получат ошибку / исключение, потому что тогда у вас может быть стратегия супервизора, пытающаяся перезапустить Buzz в то время как обратный вызов пытается сделать что-то другое (возможно, конфликтующее) с исключением.

Обратите внимание: хотя это определенно не является обязательным требованием, я был бы очень признателен, если бы любые предоставленные фрагменты кода были на Java, а не на Scala (для меня Scala выглядит иероглифами)!

1 ответ

То, что делает запрос, - это, в основном, запуск временного субъекта, который будет отправителем сообщения, чтобы, когда получатель отвечает, он оказался в этом временном субъекте. Временный актер создает Promise и отдает Future для звонящего. Если ответ приходит до истечения указанного времени, временный субъект завершает Promise с успешным результатом.

Наблюдение всегда происходит у актеров, и, поскольку запрос реализован с использованием актера, в этом взаимодействии нет ничего отличного от случайного другого актера, отправляющего ему сообщение, которое могло бы заставить надзор работать иначе.

В вашем случае исключение возникнет у родительского субъекта, чтобы он мог контролировать ребенка. Затем, если вы не отправите ответное сообщение, вызванное этой ошибкой, истечет время ожидания ask-актор провалит будущее с AskTimeoutException,

Таким образом, так как этот сбой может достичь родителя двумя способами, обычно не стоит использовать шаблон запроса с родительским взаимодействием.

Другие вопросы по тегам