Найти актера по номеру персистентности
У меня есть система, в которой есть актер на пользователя. Пользователи отправляют сообщения редко, но когда они это делают, они отправляют обычно не одно, а несколько.
В настоящее время у меня есть карта, где я храню persistenceId -> ActorRef
, Когда я получаю новое сообщение для актера, я смотрю на карту, если есть ActorRef, я использую его. Если это отсутствует, я создаю это и помещаю это в карту. Конечно, я не хочу иметь 2 экземпляра одного и того же актера персистентности одновременно. Кроме того, я не хочу создавать и уничтожать актера для каждого сообщения, так как восстановление может занять некоторое время.
Я чувствую, что должен быть какой-то более чистый способ "найти или создать" актера. Что-то вроде actorSystem.getOrCreate(persistenceId, props)
, Я думал, что осколок может помочь мне с этим, но я не мог найти точный пример этого. Кроме того, я знаю, что есть actorSelection
, который имеет недостатки:
- использовать его в слишком многих местах, с жестко закодированными путями, которые сложно поддерживать
- использование его для отправки слишком большого количества сообщений, так как это снижает производительность
Таким образом, в основном вопрос заключается в том, каков наилучший способ размещения субъекта персистентности в одном сервисе, если для субъекта персистентности используется идентификатор пользователя. Если я решу использовать шардинг, то это будет 1 шард на актера. Это нормально?
1 ответ
Разделение актеров - это почти то, что вам нужно - вы можете думать об этом как о распределенной карте актеров, и нет необходимости в дополнительных решениях. Осколок заботится о вызове актера за кулисы, и вам не нужно управлять актерами самостоятельно.
val sharding = ClusterSharding(system).start(
typeName = CustomerActor.shardName,
entityProps = CustomerActor.props,
settings = ClusterShardingSettings(system),
extractEntityId = CustomerActor.extractEntityId,
extractShardId = CustomerActor.extractShardId)
}
где extractEntityId
это функция, которая направляет сообщения соответствующим субъектам
val extractEntityId: ShardRegion.ExtractEntityId = {
case gc: GetCustomer => (gc.customerId, gc)
}
И последний пример:
case class GetCustomer(customerId: String)
sharding ! GetCustomer("customer-id")
Более подробная информация здесь https://doc.akka.io/docs/akka/2.5/cluster-sharding.html