Akka cluster-sharding: могут ли участники Entry иметь динамические свойства

Похоже, что Akka Cluster-Sharding хорошо сочетается с вариантом использования, в котором я должен создавать отдельные экземпляры постоянных субъектов с отслеживанием состояния на узлах Akka.

Я не понимаю, возможно ли иметь тип субъекта Entry, который требует аргументов для его создания. Или, может быть, мне нужно пересмотреть, как субъект 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 принимает один экземпляр Props для создания всех участников Entry.

Из akka cluster-sharding:

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

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

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
}

}

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


person Rich    schedule 20.10.2014    source источник


Ответы (1)


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

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

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

val par1: Option[param1Type] = None

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

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

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

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

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 для каждого творения? Обратной стороной этого является то, что в том варианте, который он работает, вам нужно избегать изменения значения providedPar1 до тех пор, пока вы не будете на 100% уверены, что актер был создан, или вы можете рискнуть, что он получит доступ к новому, неправильному значению (yay , условия гонки!)

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

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

person Diego Martinoia    schedule 23.10.2014
comment
Спасибо за идеи. В качестве прямого ответа на первую часть вопроса, который мы только подразумевали, нет встроенного способа ClusterSharding для поддержки динамических свойств. Таким образом, ваш ответ контекстуализируется как относящийся к моему последующему вопросу: «Это мой лучший вариант?» Думаю, вы хорошо ответили. - person Rich; 23.10.2014
comment
Да, я не был уверен, лучше ли удалить его полностью или пометить как неработающий, чтобы, возможно, кто-то в akka забрал его подмигнуть, подмигнуть (или, по крайней мере, люди узнают, что это не вариант и не буду тратить время на попытки). Кроме того, возможно, удастся получить что-то с Guice и взломать InjectedProps, я где-то видел что-то подобное, к сожалению, я не помню подробностей. - person Diego Martinoia; 24.10.2014