通过 AKKA 中的 worker actors 检索状态 actors

Retrieving state actors through worker actors in AKKA

我有三个参与者来处理 CQRS 场景。 ProductWorkerActor 处理命令部分,ProductQueryWorkerActor 处理查询部分,ProductStateActor 处理状态部分。

我处理查询的方式是使用:

ProductQueryWorkerActor.Ask<ProductState>("give-me-product-state-for-product-1000")

来自 ProductQueryWorkerActor 的代码:

if (message == "give-me-product-state-for-product-1000")
{
    var actor = Context.ActorSelection("akka://catalogSystem/user/productState/1000");
    var psDTO = actor.Ask<ProductStateDTO>(message).Result;
    Sender.Tell(ps);
}

请忽略用于访问产品状态的路径。它是硬编码的,有意使代码阅读起来更简单。

  1. 我是否应该像我在这种情况下使用的那样使用 Ask 来检索产品状态? Ask 是期货吗?

  2. 我应该将状态作为 DTO 公开给外部工作而不是 actor 本身吗?

  3. 要更改产品的任何状态,我应该在 ProductWorkerActor 中还是在 ProductStateActor 本身中处理消息?第二种情况,ProductWorkerActor发送消息给ProductStateWorkerProductStateWorker处理消息,改变状态并向 ProductWorkerActor 发送另一条消息,表明它通过了验证并更改了状态。

如果您对演员使用事件溯源,我建议您使用 Akka.Persistence。它处理 read/write 演员分离,并会减轻你的负担。

如果不是,在我看来,您设计的基本问题是,虽然您有单独的参与者供 reading/writing 声明,但状态本身仅由一个参与者处理。为什么? CQRS 的要点之一是拥有一个单独的模型,针对它们的角色(读或写)进行优化。

在示例中:您可以让一个处理程序 actor(例如 ProductActor)根据传入的命令更改其状态,以及一堆不同的只读 actor(例如ProductHistoryActorProductListActor),每个都有针对其角色优化的状态。 Readonly actor 可以订阅事件流来监听关于 handler actor 状态变化的传入消息并相应地更新它们自己的状态,而 handler actor 在处理命令后使用 actor 系统的事件流发布关于状态变化的消息。

广告。 1:在我看来,使用 Ask 在 actor 之间进行通信是一种反模式。在您的示例中,您使用查询参与者将消息传递给状态参与者,然后阻塞当前参与者直到响应到达(这对性能非常不利)只是为了将消息发送回发件人。而不是使用:

var psDTO = actor.Ask<ProductStateDTO>(message).Result;
Sender.Tell(ps);

你可以简单地写:

actor.Forward(message);

并让 actor 直接向发送者发送响应(您查询演员不需要参与发送响应)。

广告。 2:这取决于您的情况,但请记住 - 永远不要将可变对象作为消息传递,尤其是在发送后使用它们时。

广告。 3:我认为在你的例子中 ProductWorkerActorProductStateWorker 之间的区别是人为的。从你展示的内容来看,它们应该是一个单一的实体 IMO。