Принципы дизайна Akka

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

Итак, проблема в том, что у меня есть один родительский актер, давайте назовем его «Connector», у Connector есть поведение, описывающее, что он должен делать, когда получает экземпляр ConnectCommand. Сначала он отправляет форму с использованием HttpClient, затем переходит к паре URL-адресов, чтобы проверить некоторые параметры сеанса, и в конечном итоге отправляет Отправителю (называемому «Потребителем») сообщение о соединении, содержащее все, что ему нужно для использования API.

Теперь, я большой поклонник, чтобы сказать, не так много тянуть / спрашивать, так что реализация этого, на мой взгляд, трудная задача. Давай пройдемся по этому. Все ответы, возвращаемые HttpClientActor, являются экземпляром Response, поэтому первое, что пришло в голову, - это определение нескольких типов поведения, определенных в моем акторе, и постепенно, после завершения определенного этапа процесса подключения, измените поведение на следующий этап.

private final PartialFunction<Object, BoxedUnit> inital = ReceiveBuilder
    .match(ConnectCommand.class, c -> this.startConnection())
    .matchAny(this::unhandled)
    .build();

private final PartialFunction<Object, BoxedUnit> stage1 = ReceiveBuilder
    .match(Response.class, this::stage1)
    .matchAny(this::unhandled)
    .build();

private final PartialFunction<Object, BoxedUnit> stage2 = ReceiveBuilder
    .match(Response.class, this::stage2)
    .matchAny(this::unhandled)
    .build();

private final PartialFunction<Object, BoxedUnit> stage3 = ReceiveBuilder
    .match(Response.class, this::stage3)
    .matchAny(this::unhandled)
    .build();

private final PartialFunction<Object, BoxedUnit> stage4 = ReceiveBuilder
    .match(Response.class, this::stage4)
    .matchAny(this::unhandled)
    .build();

private final PartialFunction<Object, BoxedUnit> stage5 = ReceiveBuilder
    .match(Response.class, this::stage5)
    .matchAny(this::unhandled)
    .build();

private final PartialFunction<Object, BoxedUnit> stage6 = ReceiveBuilder
    .match(Response.class, this::stage6)
    .matchAny(this::unhandled)
    .build();

private final PartialFunction<Object, BoxedUnit> stage7 = ReceiveBuilder
    .match(Response.class, this::stage7)
    .matchAny(this::unhandled)
    .build();

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

Сейчас я чувствую, что этот актер нуждается в хороших изменениях, но, на мой взгляд, есть две альтернативы.

Первый включает в себя разделение каждого запроса HttpRequest и Response на отдельный Actor и агрегирование результатов в акторе Connector. Преимущество этого метода в том, что он очень удобочитаемый, использует функцию Tell и не должен снижать производительность, поскольку Akka создан для работы с большим количеством актеров. Единственный недостаток этого заключается в том, что мне нужно создать много контейнерных классов для этих частей состояния, которые должны быть доставлены из Stage5Actor в актер Connector. Это приводит к большим накладным расходам памяти (поправьте меня, если я ошибаюсь).

Второй подход заключается в использовании шаблона Ask для объединения шагов. Это привело бы к единственному действующему субъекту Connector, и, поскольку Spray делает то же самое для своего Http-клиента, я думаю, что это может быть правильным решением. Единственным недостатком этого является то, что, поскольку все находится поверх внешнего Http API, могут возникнуть проблемы с тайм-аутами. Если команда Akka рекомендует этот подход, как справиться со всеми таймаутами, которые абсолютно непредсказуемы.

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

Если вы чувствуете, что есть намного лучшее решение, чем те, что я упомянул, пожалуйста, сообщите! Я действительно наслаждаюсь Akka a.t.m. и каждый совет, который я получаю, - это опыт и знания не только для меня, но и для всего сообщества: D. Плюс я думаю, что это проблема, с которой все чаще сталкиваются люди.

Заранее спасибо и большое спасибо команде Akka за создание такой классной библиотеки!

PS. Этот вопрос был впервые задан на самом github Akka, но я решил опубликовать его здесь, потому что это такой же вопрос, связанный с моделью актера, как вопрос, связанный с Akka.

Ссылка на вопрос на github:https://github.com/akka/akka/issues/16080

Ответы на вопрос(1)

Ваш ответ на вопрос