使用Akka.NET的演员模型:如何防止向死亡演员发送消息

时间:2014-12-22 13:36:31

标签: akka actor akka.net

我正在使用Akka.NET来实现一个actor系统,其中一些actor按需创建并在可配置的空闲时段后被删除(我使用Akka的“ReceiveTimeout”机制)。这些演员中的每一个都由一个键标识,并且不应该存在两个具有相同键的演员。

这些演员目前由共同主管创建和删除。如果具有此键的actor尚不存在,则可以要求主管返回对匹配给定键的actor的引用,方法是返回现有键或创建新键。当演员收到“ReceiveTimeout”消息时,它会通知主管,而主管又用“PoisonPill”杀死它。

在删除这些演员之后立即向其中一个演员发送消息时我遇到了问题。我注意到向死亡演员发送消息不会产生异常。更糟糕的是,当发送“询问”消息时,发件人仍然被阻止,无限期地(或直到超时)等待他永远不会收到的回复。

我首先考虑过Akka的“Deatchwatch”机制来监控演员的生命周期。但是,如果我没有弄错的话,死亡演员发送的“终止”消息将被监视演员异步地接收,就像任何其他消息一样,因此问题可能仍然发生在目标演员的死亡和其接收之间“终止”消息。

为了解决这个问题,我做了这个,以便任何要求主管引用这样一个演员的人必须向主管发送一个“关闭会话”消息,以便在他不再需要时释放演员(这个由一次性“ActorSession”对象透明地完成。只要演员有任何公开会话,主管就不会删除它。

我认为这种情况非常普遍,因此我想知道是否没有更简单的模式来解决这类问题。任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:3)

  

在删除这些演员之后立即向其中一个演员发送消息时我遇到了问题。我注意到向死去的演员发送消息并不会产生异常。

这是设计的。尝试发送消息时,您永远不会收到异常 - 它将被简单地路由到Deadletters并记录。有很多原因导致我不能进入这里,但最重要的是这是预期的行为。

DeathWatch是这项工作的正确工具,但正如您所指出的那样 - 在您向该演员发送消息后,您可能会收到Terminated消息。

比跟踪打开/关闭会话更简单的模式是使用Ask +等待+硬超时来简单地使用来自收件人的确认/回复消息。当然,缺点是,如果您的收件人演员有很多长时间运行的操作,那么您可能会在发件人内部长时间阻止。

您可以使用的另一个选项是重新设计您的收件人角色以充当状态机并具有用于排空的软终止终止状态与潜在发件人的连接/引用。这样原来的演员仍然可以回复和接受消息,但让来电者知道它不再可用于工作。

答案 1 :(得分:0)

我通过Akka的Cluster Sharding机制创建的实体演员解决了这个问题:

  

如果实体的状态是持久的,您可以停止不用于减少内存消耗的实体。这是通过实体actor的应用程序特定实现来完成的,例如通过定义接收超时(context.setReceiveTimeout)。如果消息在实体停止时已经排队,则将删除邮箱中的排队消息。为了支持优雅的钝化而不丢失此类消息,实体actor可以将ShardRegion.Passivate发送到其父Shard。 Passivate中指定的包装消息将被发送回实体,然后该实体应该自行停止。在接收Passivate和终止实体之间,Shard将缓冲传入的消息。此后,这些缓冲的消息被传递给实体的新版本。