【问题标题】:In Akka Typed Cluster Sharding, is it safe to persist an EntityRef for future use?在 Akka Typed Cluster Sharding 中,持久化 EntityRef 以供将来使用是否安全?
【发布时间】:2021-01-30 09:24:36
【问题描述】:

我目前正在考虑让两个不同的持久性参与者相互通信。特别是:

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)
       )
    }
}

有人对此有任何见解吗?

【问题讨论】:

    标签: akka akka-cluster akka-persistence akka-typed


    【解决方案1】:

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

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

    在那之前,您不应该将 EntityRefs 放入消息、事件或快照状态:相反,您基本上必须将 ID 放入这些对象中,并将包装在 ShardingEnvelopes 中的消息发送给分片区域参与者(这就是EntityRef.tell 所做的)。在某些情况下,在非持久子actor中维护实体ID到EntityRefs的映射并通过该子actor向EntityRefs发送消息可能是合理的,或者如果愿意阻止或真正扭曲您的协议,请那个孩子为你解决EntityRefs。

    请注意,从 Akka 2.6.13 开始,可以实现自定义序列化程序来处理 EntityRefs; Jackson 序列化程序此时不支持EntityRef。将类型键和实体 ID 解析为 EntityRef 的方法必须注入到序列化程序中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-30
      • 1970-01-01
      • 1970-01-01
      • 2019-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多