我知道Akka和演员模型在DDD方法中工作得很好。但是,我确实有一个关于层次结构的问题。
假设我有一个可以向用户发送消息的系统,我可能有一个UserActor
和一个MessageActor
。
+-----------+ +--------------+
(CreateUser)->| UserActor | | MessageActor |<-(CreateMessage)
|-----------| |--------------|
| + id | | + id |
+-----------+ | + userId |
+--------------+
# The hierarchy is "flat":
/system
/user
/message
有时,我们可能要禁用某个用户,并且不希望该用户接受任何新消息。
让UserActor
接收CreateMessage
和Disable
命令似乎很有用,这样禁用的用户就可以拒绝新消息,而不必在其他地方保持该状态。
+------------+ +--------------+
(CreateUser)->| UserActor | | MessageActor |
|------------| |--------------|
| + id | /->| + id |
(CreateMessage)->| + messages |--/ +--------------+
+------------+
# The hierarchy is a true hierarchy:
/system
/user
/message
这是一种常见的用法吗?还是限制子参与者的数量并使用其他机制来维护约束更好?
谢谢
1条答案
按热度按时间g9icjywg1#
有时候,将聚合的组成实体建模为某个根的子参与者是有用的:聚合所需的大量事务保证可以通过集群分片(或在非集群情况下id到
ActorRef
s的Map)来提供,但由于您将实体建模为多个actor,因此actor模型的一次一个消息处理将不适用。绕过该限制的方法是在聚合的根actor中使用stashing:当它将处理过程推迟给它的孩子时,如果它隐藏了传入的命令,那么整个参与者的星座仍然会作为一个整体呈现给外部世界。因为Akka Typed(通常推荐)让一个持久化actor也有子对象有点笨拙(特别是在Scala中),所以在这样做时,我倾向于有一个子对象专门用于管理根的持久化(这个子对象可以是持久化API上的一个非常薄的 Package 器,例如,你可能有一个像
PersistEvents
这样的命令,它将在成功时用更新的状态进行回复)。这在以下情况下特别有用:在聚合状态中可以有任意多个实体,但您不希望必须加载到内存中的状态总是包含所有这些实体(例如,按需加载所需的内容)。表示长期存在的事物的聚合是一个用例,您保留查看历史的权利。
因此,在这种方法中,root actor通常会:
从本质上讲,这是一个 Saga ,尽管如果与孩子的互动是有效的幂等的,你可以省去让传奇故事本身持续下去。