Я нахожусь в очень похожей ситуации, что и ваша. У меня нет точного ответа, но я могу поделиться с вами и читателями тем, что я сделал / попробовал / подумал.
Вариант 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