在Akka类型的集群分片中,保存EntityRef以备将来使用是否安全?

在Akka类型的集群分片中,保存EntityRef以备将来使用是否安全?,akka,akka-cluster,akka-persistence,akka-typed,Akka,Akka Cluster,Akka Persistence,Akka Typed,我目前正在考虑让两个不同的角色相互交流。特别是: Given an Actor A exists When an Actor B is spawned Then Actor B must have a reference to Actor A And Actor B must be able to continuously send messages to Actor A even after relocation 我知道有两种选择: // With an EntityRef val coun

我目前正在考虑让两个不同的角色相互交流。特别是:

Given an Actor A exists
When an Actor B is spawned
Then Actor B must have a reference to Actor A
And Actor B must be able to continuously send messages to Actor A even after relocation
我知道有两种选择:

// With an EntityRef
val counterOne: EntityRef[Counter.Command] = sharding.entityRefFor(TypeKey, "counter-1")
counterOne ! Counter.Increment

// Entity id is specified via an `ShardingEnvelope`
shardRegion ! ShardingEnvelope("counter-1", Counter.Increment)
第二个选项似乎是一个不错的选择,因为我将把实体的实际引用的解析委托给Akka。我可能只需要在实例化时将一些包装器函数传递给我的参与者。比如说

val shardRegionA: ActorRef[ShardingEnvelope[Counter.Command]] =
  sharding.init(Entity(TypeA)(createBehavior = entityContext => A()))

def delegate_A(id,message) = {
    shardRegionA ! ShardingEnvelope(id,message)
}

val shardRegionB: ActorRef[ShardingEnvelope[Counter.Command]] =
  sharding.init(Entity(TypeB)(createBehavior = entityContext => B(delegate_A)))

--------

object B {
    def apply(delegate) = {
        ...somewhere inside the state...
        delegate("some_id_of_A", Message("Hello"))
        ...somewhere inside the state...
    }
}

但是,我还想了解第一个选项是否更简单,因为
EntityRef
可能在状态/事件中是安全持久的

object B {
    def apply(entityRefA : EntityRef[A]) = {
       EventSourcedBehavior[...](
           emptyState = State(entityRefA)
       )
    }
}


有人对此有什么见解吗?

EntityRef
在状态/事件中不能安全地持久化(除非是一些非常脆弱的基于反射的序列化),因为它不会公开允许反序列化程序重建等效的
EntityRef
的信息。默认的Jackson序列化也不能有效地反序列化
EntityRef
s

截至本答案发布时,存在一个允许提取
EntityRef
的“定义”组件进行序列化的更新(例如,so
EntityRef[Employee.Command]
可以JSON序列化为
{“entityId”:“123456789”,“typeKey”:“Employee”}
。对于包含
EntityRef
s的任何消息、持久化事件或状态(如果快照),PR仍然需要自定义序列化,但至少可以在此类对象中包含
EntityRef
s

在此之前,您不应该将
EntityRef
s放入消息、事件或快照表状态:相反,您基本上必须将ID放入这些对象中,并将
ShardingEnvelope
s中包装的消息发送给shard region参与者(这就是
EntityRef.tell
的作用)。在某些情况下,在非持久子参与者中维护实体ID到
EntityRef
s的映射,并通过该子参与者将消息发送到
EntityRef
s可能是合理的,或者如果愿意阻止或真的扭曲您的协议,请确实要求该子参与者为您解析
EntityRef
s