Akka、DDD和作为聚合体的参与者层级

ie3xauqp  于 2023-04-11  发布在  其他
关注(0)|答案(1)|浏览(118)

我知道Akka和演员模型在DDD方法中工作得很好。但是,我确实有一个关于层次结构的问题。
假设我有一个可以向用户发送消息的系统,我可能有一个UserActor和一个MessageActor

+-----------+    +--------------+
(CreateUser)->| UserActor |    | MessageActor |<-(CreateMessage) 
              |-----------|    |--------------|
              | + id      |    | + id         |
              +-----------+    | + userId     |
                               +--------------+

# The hierarchy is "flat":
 /system
    /user
    /message

有时,我们可能要禁用某个用户,并且不希望该用户接受任何新消息。
UserActor接收CreateMessageDisable命令似乎很有用,这样禁用的用户就可以拒绝新消息,而不必在其他地方保持该状态。

+------------+      +--------------+
   (CreateUser)->| UserActor  |      | MessageActor | 
                 |------------|      |--------------|
                 | + id       |   /->| + id         |
(CreateMessage)->| + messages |--/   +--------------+
                 +------------+                       

# The hierarchy is a true hierarchy:
/system
   /user
       /message

这是一种常见的用法吗?还是限制子参与者的数量并使用其他机制来维护约束更好?
谢谢

g9icjywg

g9icjywg1#

有时候,将聚合的组成实体建模为某个根的子参与者是有用的:聚合所需的大量事务保证可以通过集群分片(或在非集群情况下id到ActorRef s的Map)来提供,但由于您将实体建模为多个actor,因此actor模型的一次一个消息处理将不适用。绕过该限制的方法是在聚合的根actor中使用stashing:当它将处理过程推迟给它的孩子时,如果它隐藏了传入的命令,那么整个参与者的星座仍然会作为一个整体呈现给外部世界。
因为Akka Typed(通常推荐)让一个持久化actor也有子对象有点笨拙(特别是在Scala中),所以在这样做时,我倾向于有一个子对象专门用于管理根的持久化(这个子对象可以是持久化API上的一个非常薄的 Package 器,例如,你可能有一个像PersistEvents这样的命令,它将在成功时用更新的状态进行回复)。
这在以下情况下特别有用:在聚合状态中可以有任意多个实体,但您不希望必须加载到内存中的状态总是包含所有这些实体(例如,按需加载所需的内容)。表示长期存在的事物的聚合是一个用例,您保留查看历史的权利。
因此,在这种方法中,root actor通常会:

  • 接到命令
  • 找出哪些孩子(如果有的话)需要被衍生
  • 直接对孩子下达内部指令
  • 等待回复,在收到回复前隐藏传入的命令

从本质上讲,这是一个 Saga ,尽管如果与孩子的互动是有效的幂等的,你可以省去让传奇故事本身持续下去。

相关问题