2014-10-20 2 views
7

Akka Cluster-Sharding выглядит так, как будто он хорошо подходит для использования. Мне нужно создать отдельные экземпляры постоянных участников с постоянным статусом через узлы Akka.Akka cluster-sharding: Can Entry артисты имеют динамические реквизиты

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

Object Account { 
    def apply(region: String, accountId: String): Props = Props(new Account(region, accountId)) 
} 

class Account(val region: String, val accountId: String) extends Actor with PersistentActor { ... } 

В то время как ClusterSharding.start занимает в единственном экземпляре реквизита для создания всех участников записи.

akka cluster-sharding От:

val counterRegion: ActorRef = ClusterSharding(system).start(
    typeName = "Counter", 
    entryProps = Some(Props[Counter]), 
    idExtractor = idExtractor, 
    shardResolver = shardResolver) 

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

def getEntry(id: EntryId): ActorRef = { 
val name = URLEncoder.encode(id, "utf-8") 
context.child(name).getOrElse { 
    log.debug("Starting entry [{}] in shard [{}]", id, shardId) 

    val a = context.watch(context.actorOf(entryProps, name)) 
    idByRef = idByRef.updated(a, id) 
    refById = refById.updated(id, a) 
    state = state.copy(state.entries + id) 
    a 
} 

}

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

ответ

10

Я в очень похожей ситуации, такой как ваша. У меня нет точного ответа, но я могу поделиться с вами и читателями тем, что я сделал/пытался/думал.

Вариант 1) Как вы упомянули, вы можете извлечь информацию об идентификаторе, осколке и области из того, как вы называете свой материал и разбираете его. Верх - a) что это легко сделать. Недостатки в том, что a) Akka кодирует пути актеров как UTF-8, поэтому, если вы используете что-либо в качестве разделителя, не являющегося стандартным символом url (например, || или w/e), вам необходимо его сначала декодировать от utf8. Обратите внимание, что внутри Akka utf8 жестко закодирован как метод кодирования, нет способа извлечь формат кодировки как в функции, поэтому, если завтра изменение akka вам придется также адаптировать свой код. б) ваша система больше не сохраняет гомоморфизм (что вы подразумеваете под «это выглядит немного хаки»). Это означает, что вы добавляете риск того, что ваши данные в один прекрасный день могут содержать строку разделителя информации в качестве значимых данных, и ваша система может испортиться.

Вариант 2) Осколок породит вашего актера, если он не существует. Таким образом, вы можете заставить свой код всегда отправлять сообщение init не инициализированным участникам, которое содержит ваши параметры конструктора. Ваши sharded актеры будут иметь что-то внутри них вид:

val par1: Option[param1Type] = None 

def receive = { 
    case init(par1value) => par1 = Some(par1value) 
    case query(par1) => sender ! par1 
} 

А из вашего региона доступа актера вы всегда можете отправить первое сообщение запроса, а затем сообщение инициализации, если возвращение является None. Это предполагает, что ваш субъект доступа к региону не содержит список инициализированных участников, и в этом случае вы можете просто запустить с помощью init, а затем использовать их в обычном режиме. Достоинством является а) Это элегантный б) «чувствует себя» правильно

Даунсайд: а) принимает 2x сообщения (если вы не поддерживаете список инициализированных актеров)

Вариант 3) ЭТО ВАРИАНТ ИСПЫТАЛ И НЕ РАБОТАЕТ. Я просто оставлю это здесь для людей, чтобы не тратить время на то, чтобы попытаться. Я понятия не имею, работает ли это, я не тестировал, потому что я использую этот сценарий в производстве со специальными ограничениями, а фантастические вещи не допускаются^_^Но не стесняйтесь, пожалуйста, дайте мне знать с pm или комментарий! В принципе, вы начинаете свой регион с

val counterRegion: ActorRef = ClusterSharding(system).start(
    typeName = "Counter", 
    entryProps = Some(Props[Counter]), 
    idExtractor = idExtractor, 
    shardResolver = shardResolver) 

Что делать, если вы, в вашем регионе создание актера, сделать что-то вроде:

var providedPar1 = v1 
def providePar1 = providedPar1 

val counterRegion: ActorRef = ClusterSharding(system).start(
    typeName = "Counter", 
    entryProps = Some(Props(classOf[Counter], providePar1), 
    idExtractor = idExtractor, 
    shardResolver = shardResolver) 

И тогда вы измените значение providedPar1 для каждого творения? Недостатком этого является то, что в варианте, который он работает, вам нужно будет не изменять значение предоставленногоPar1 до тех пор, пока вы не на 100% не уверены в том, что актер создан или вы рискуете получить доступ к новому неправильному значению (yay , условия гонки!)

В общем, вам лучше с вариантом 2 imho, но в большинстве сценариев риски, введенные 1, малы, и вы можете смягчить их должным образом, учитывая преимущества простоты (и производительности).

Надеюсь, что эта напыщенная речь поможет, сообщите мне, если вы попробуете 3, как это работает!

+1

Спасибо за идеи. В качестве прямого ответа на первую часть вопроса, который мы подразумеваем, встроенный способ ClusterSharding не поддерживает встроенный динамический реквизит. Итак, чтобы контекстуализировать ваш ответ как относящийся к моему следующему вопросу о «это мой лучший вариант?» Который я считаю, что вы хорошо ответили. – Rich

+0

Да, я не был уверен, было ли лучше удалить его полностью или пометить его как нерабочее, чтобы кто-то из akka заберет его * wink wink * (или, по крайней мере, люди будут знать, что это не вариант и не будет тратить время пытается это). Кроме того, возможно, было бы возможно получить что-то с Guice и взломать InjectedProps, я где-то видел что-то подобное, к сожалению, я не помню деталей. –

 Смежные вопросы

  • Нет связанных вопросов^_^