当前位置: 首页 > 知识库问答 >
问题:

演员模型与阿卡。NET:如何防止向已死的参与者发送消息

桂玉石
2023-03-14

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

这些参与者当前由一个普通主管创建和删除。可以要求主管返回与给定密钥匹配的参与者的引用,如果具有该密钥的参与者尚不存在,则可以返回现有的参与者,也可以创建新的参与者。当一个参与者收到“ReceiveTimeout”消息时,它会通知主管,主管会用“毒药丸”杀死它。

我有一个问题,当一个消息被删除后立即发送给这些演员之一。我注意到向死去的演员发送消息不会产生异常。更糟糕的是,当发送“询问”消息时,发送者仍然被阻止,无限期(或直到超时)等待他永远不会收到的响应。

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

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

我认为这种情况很常见,因此我想知道是否有一种更简单的模式来解决这种问题。如有任何建议,将不胜感激。

共有2个答案

梁华皓
2023-03-14

我通过Akka的集群分片机制创建的实体参与者解决了这个问题:

如果实体的状态是持久的,则可以停止未用于减少内存消耗的实体。这是由实体参与者的应用程序特定实现完成的,例如通过定义接收超时(context.setReceiveTimeout)。如果消息在实体停止时已经排队到实体,则邮箱中排队的消息将被删除。为了支持优雅的钝化,而不丢失这样的消息,实体参与者可以发送碎片区域。钝化到它的父碎片。钝化中指定的包装消息将被发回实体,然后实体应该停止自己。在接收到钝化和终止实体之间,传入的消息将由碎片缓冲。这种缓冲的消息随后被传递到实体的新化身。

刁俊人
2023-03-14

我有一个问题,当发送消息给这些演员之一后,它已被删除。我注意到向死去的演员发送消息不会产生异常。

这是故意的。在尝试发送消息时,您永远不会收到异常-它只会被路由到死信并被记录。有很多原因我不想在这里讨论,但底线是这是有意的行为。

DeathWatch是这项工作的合适工具,但正如您所指出的,您可能会在向该参与者发送消息后收到一条终止的消息。

比跟踪打开/关闭会话更简单的模式是简单地使用接收方的确认/回复消息,使用询问等待硬超时。当然,不利的一面是,如果您的收件人参与者有很多长时间运行的操作,那么您可能会在发件人内部阻塞很长一段时间。

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

 类似资料:
  • 我希望避免给终止的参与者发送死信消息,并避免向该参与者发送消息 actorSelection没有像我预期的那样工作,从ping发送的最后一条消息仍然以一纸空文告终: [信息][09/16/2016 00:47:46.237][MyActorSystem-Akka.Actor.Default-Dispatcher-4][Akka://MyActorSystem/User/PingActor/Pong

  • 考虑下面的代码示例(版本1)。在这里,父角色(ActorA)向子角色(ActorB)发送消息,然后停止自我。由于父角色的自停止,在高负载下,子角色甚至在从邮箱提取邮件之前就会死亡,因此邮件变成了“死信”(参见下面的示例输出1)。 由于某些原因,我无法修改应用程序设计以删除父参与者的自停止。 版本1 样本输出1 现在考虑下面的代码修改(版本2)。通过将消息确认从子参与者引入到父参与者,然后在收到此确

  • 我是阿克卡的乞丐,在我接受教育期间,我有一个问题: 例如,我有一个主参与者,它向其他两个子参与者发送消息。它们都将返回不同的列表。 我如何匹配主要演员来处理这些反应? 一些演示代码: 儿童演员之一:

  • 我只是从阿卡开始,我试图将一些混乱的功能分成更容易管理的部分,每个部分都由不同的演员执行。 我的任务似乎正是适合演员模式的。我有一个对象树,它们保存在数据库中。每个节点都有一些属性;让我们只关注一个,称之为财富。孩子的财富取决于父母的财富。当计算节点上的财富时,这应该会在子节点上触发类似的计算。我想收集节点的所有更新实例,并同时将它们保存在数据库中。 这似乎很简单:一个参与者只需执行计算,然后为当

  • 是否有方法获取创建actor的类。例如,我有一个actorRef或actor selection实例,我想从中获取创建现有actor的类。提前感谢您的回复!

  • 我有父母和孩子。每个儿童演员控制一个装置。当我创建所有的子角色时,我给他们一个uuid。 每个子参与者都是通过设备配置创建的,当配置更改时,我希望通过以下方式重新创建参与者: > 停止旧的: 最终的未来停止了=优雅的停止(actorRef,Duration.create(1,时间单位。秒)); Await.result(停止,Duration.create(1, TimeUnit.二)); 重新创