2015-05-19 100 views
3

我有三个演员来处理CQRS场景。 ProductWorkerActor处理命令部分,ProductQueryWorkerActor处理查询部分和ProductStateActor处理状态部分。通过AKKA中的工人演员检索状态演员

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

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. 我应该使用我在这种情况下,已经使用检索产品的状态?被称为期货吗?

  2. 我是否应该将DTO的状态暴露给外部工作而不是演员本身?

  3. 要更改产品的任何状态,我应该处理的消息处理ProductWorkerActorProductStateActor本身?在第二种情况下,ProductWorkerActor将消息发送到ProductStateWorker,所述ProductStateWorker处理该消息,改变状态和发送另一消息ProductWorkerActor,它通过了验证,并改变了状态。

回答

4

如果您与演员一起使用Event Sourcing,我建议您使用Akka.Persistence。它处理读写操作者的分离,并会承担你肩上的很多负担。

如果不是,我认为你的设计的基本问题是,虽然你有独立的演员读/写状态,但状态本身只在一个演员中处理。为什么? CQRS的一个要点是要有一个单独的模型,用于服务他们的角色(读或写)。

在示例:你可以有一个句柄演员改变其基于传入命令状态,很多不同只读演员,每个都有它自己的状态以优化他们的(如ProductActor。)(例如ProductHistoryActorProductListActor)。角色。只读角色可以订阅事件流来监听处理器角色状态变化的传入消息并相应地更新他们自己的状态,而处理命令后处理命令的角色则使用角色系统的事件流发布关于状态变化的消息。

Ad。 1:在我看来,使用Ask在演员之间进行沟通是一种反模式。在你的例子中,你使用查询actor将消息传递给状态actor,然后阻塞当前的actor,直到响应到达(这对性能非常糟糕),只是将消息发送回发件人。而不是使用:

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

,你可以简单地写:

​​

,让直接actor发送响应给发件人(您查询的演员并不需要发送响应参与)。

Ad。 2:这取决于你的情况,但要记住 - 你不应该把可变对象作为消息传递,特别是当你在发送后使用它们。

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

+0

关于第1和第2点的优秀答案我有灵感将杰克艾伦的Essential AKKA书中的工作者演员和国家演员分开。因为他建议分开国家和行为。 –

+0

'actor.Forward'不起作用,因为actor是ActorSelection。 ActorSelection没有Forward扩展。我不确定如何从ActorSelection中获取潜在的演员,以便我可以进行转发。 –

+0

转发基本上相当于'Tell(message,Sender)'。在处理演员选择时也要小心 - 如果他们不是非常必要的话,不应该使用他们。那里有一些[讲座](https://petabridge.com/blog/when-should-I-use-actor-selection/)。 – Horusiath