如何解决在 Akka Typed Cluster Sharding 中,保留 EntityRef 以备将来使用是否安全?
我目前正在考虑让两个不同的持久 actor 相互通信。特别是:
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。我可能只需要在实例化时将一些包装函数传递给我的 Actor。例如
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
。
截至本答案发布时,有一个 PR 允许提取 EntityRef
的“定义”组件以进行序列化(例如,EntityRef[Employee.Command]
可以被 JSON 序列化为{ "entityId": "123456789","typeKey": "EMPLOYEE" }
。该 PR 仍然需要对包含 EntityRef
的任何消息、持久事件或状态(如果是快照)进行自定义序列化,但至少可以包含 EntityRef
s 在这样的对象中。
在那之前,您不应将 EntityRef
放入消息、事件或可快照状态:相反,您基本上必须将 ID 放入这些对象中,并将包裹在 ShardingEnvelope
中的消息发送到分片区域actor(这就是EntityRef.tell
所做的)。在某些情况下,在非持久性子角色中维护实体 ID 到 EntityRef
的映射并通过该子角色向 EntityRef
发送消息可能是合理的,或者如果愿意阻止或真的会扭曲你的协议,请让那个孩子为你解决EntityRef
问题。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。