Акка и государство среди актеров в кластере - PullRequest
8 голосов
/ 31 марта 2011

Я работаю над диссертационным проектом, который должен быть сервером Minecraft, написанным на scala и Akka. Сервер должен легко развертываться в облаке или кластере (не уверен, что я использую правильную терминологию ... он должен работать на нескольких узлах). Я, однако, новичок в Акке, и мне было интересно, как реализовать такую ​​вещь. Проблема, которую я пытаюсь выяснить прямо сейчас, заключается в том, как разделить состояние между участниками на разных узлах. Моей первой идеей было создать актера Camel, который будет считывать tcp-поток с клиентов Minecraft, а затем отправлять его на балансировщик нагрузки, который выберет узел, который обработает запрос, а затем отправит некоторый ответ клиенту через tcp. Допустим, у меня есть актер, реализующий AuthenticationService, который проверяет, действительны ли предоставленные пользователем учетные данные. У каждого узла будет такой актер (или, возможно, их больше), и у всех актеров должна быть постоянно одна и та же база данных (или состояние) пользователей. У меня вопрос, каков наилучший способ сохранить это состояние? Я придумал несколько решений, о которых мог бы подумать, но я не сделал ничего подобного, поэтому, пожалуйста, укажите на недостатки:

Решение № 1: Сохранить состояние в базе данных. Это, вероятно, будет очень хорошо работать для этого примера аутентификации, где состояние представлено только чем-то вроде списка имен пользователей и паролей, но, вероятно, не будет работать в тех случаях, когда состояние содержит объекты, которые не могут быть легко разбиты на целые числа и строки.

Решение № 2: Каждый раз, когда поступает запрос к определенному субъекту, который изменит его состояние, субъект после обработки запроса передает информацию об изменении всем другим субъектам того же типа, которые будут менять их состояние в соответствии с информацией, отправленной оригинальным актером. Это кажется очень неэффективным и довольно неуклюжим.

Решение № 3: Наличие определенного узла служит своего рода узлом состояния, в котором будут присутствовать акторы, представляющие состояние всего сервера. Любой другой актер, кроме актеров в таком узле, не будет иметь состояния и будет запрашивать актеров в «узле состояния» каждый раз, когда им понадобятся некоторые данные. Это также кажется неэффективным и не защищенным от ошибок.

Итак, вот оно. Единственное решение, которое мне действительно нравится, это первое, но, как я уже сказал, оно, вероятно, работает только в очень ограниченном подмножестве проблем (когда состояние может быть разбито на структуры redis). Любой ответ от более опытных гуру будет очень ценным. С уважением, Томас Герман

1 Ответ

4 голосов
/ 31 марта 2011

Решение № 1 может быть медленным.Кроме того, это узкое место и единственная точка отказа (это означает, что приложение перестает работать, если узел с базой данных дает сбой).Решение №3 имеет похожие проблемы.

Решение №2 менее тривиально, чем кажется.Во-первых, это единственная точка отказа.Во-вторых, не существует атомарности или других гарантий упорядочения (таких как регулярность) для операций чтения или записи, если только вы не выполните общий объем трансляции (который стоит дороже, чем обычная трансляция).Фактически, большинство алгоритмов распределенных регистров выполняют широковещательную рассылку изнутри, поэтому, хотя и неэффективно, это может быть необходимо.

Из того, что вы описали, вам требуется атомарность для вашего распределенного регистра.Что я имею в виду под атомарностью?Атомарность означает, что любое чтение или запись в последовательности одновременных операций чтения и записи выглядит так, как если бы это происходило в один момент времени. Неофициально , в Решении № 2 с одним действующим субъектом, содержащим регистр, это гарантирует, что если 2 последовательных записи W1, а затем W2 в регистр произойдут (что означает 2 широковещательных сообщения), то никакой другой субъект, считывающий значения изрегистр будет читать их в порядке, отличном от первого W1, а затем W2 (на самом деле это более сложный процесс).Если вы пройдете через несколько примеров последующих трансляций, когда сообщения прибывают в пункт назначения в разные моменты времени, вы увидите, что такое свойство упорядочения вообще не гарантируется.

Если упорядочение гарантируется или атомарность не возникает 'Проблема в том, что какой-то алгоритм, основанный на сплетнях, мог бы помочь медленно распространить изменения на все узлы.Это, вероятно, не очень поможет в вашем примере.

Если вы хотите полностью отказоустойчивый и атомарный, я рекомендую вам прочитать эту книгу о надежном распределенном программировании Рашида Геррауи и ЛуисаРодригес, или части, связанные с распределенными абстракциями регистров.Эти алгоритмы построены поверх уровня передачи сообщений и поддерживают распределенный регистр, поддерживающий операции чтения и записи.Вы можете использовать такой алгоритм для хранения распределенной информации о состоянии.Однако они не применимы к тысячам узлов или больших кластеров, поскольку они не масштабируются, как правило, имеют многочлен сложности по количеству узлов.

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

...