【问题标题】:akka.net actor parallel executionakka.net actor 并行执行
【发布时间】:2016-12-15 10:24:26
【问题描述】:

我们在 akka.net 上做 POC 来处理 json 文件。我正在努力寻找批处理 JArray 的最佳方法。在我的实现中,akka coordinator actor 收到以下消息:

//coordinator actor receive
public class ValidatedInput
{
public JArray Data { get; set; }
}

我的协调演员可以像下面这样一次处理完整的 JArray,但我正在努力启动并行演员的数量,每个演员将处理来自 JArray 的 50 条记录。

//coordinator actor receives messages and calls transform actor to process
public void Receiving()
{
Receive<ValidatedInput>(x =>
{
TransformerRouter.Tell(x);
});
}

//transform actor receives message and process, sample code
Receive<ValidatedInput>(x =>
{
PipeToSupport.PipeTo<TransformResult>(MapDataAsync(x).ContinueWith(data =>
{
return new TransformResult();}), Self);
});

有没有像下面这样的方法,我可以传递 50 个 JArray 记录以供每个参与者处理并收集结果,例如:

Receive<ValidatedInputDataResult>(
{
TransformerRouter.Tell(x.Data.Take(50);
});

【问题讨论】:

    标签: akka.net


    【解决方案1】:

    有一段时间没有使用 Akka.NET,但是当我使用 Akka.NET 时,我总是尽可能避免传递集合,主要原因有两个:

    • 您可以发送给参与者的消息大小有一个限制,尽管可以增加此限制this isn't recommended

    • Receive&lt;&gt;'d 时,发送给参与者的所有消息都被序列化,然后反序列化,这意味着如果您在消息中发送数组或其他对象集合,则可能会将它们分配到大对象上每次使用Tell 方法时都会堆,如果这是热代码路径,则应尽可能避免。

    我当时解决这类问题的方法是:

    • 有一个“顶级”协调演员:
      • 包含一个路由器,worker actor 位于该路由器后面。例如,您可以将路由器配置为distribute messages in a round-robin fashion
      • 每次有新消息Receive'd 时都会生成一个“聚合器”actor,worker actor 会将其结果发送到该actor。您可以使用 Tell 方法并传递聚合器的参与者引用,以便工作人员在其参与者上下文中将聚合器视为 Sender
    • “顶级”参与者中的路由器配置为automatically spawn more actors when needed
    • worker Actor 只执行Receive 一条消息,对其进行处理,然后将Tell 发送到其上下文中的Sender

    请记住,这个建议可能是不完整的,因为我当时对使用 Actor 系统不是很“流利”,而且我已经有大约 6 个月没有积极使用 Akka.NET 了,可能会有更好的方法来完成你所需要的。

    我建议在 Google 上搜索“actor system patterns”和“Scala actor patterns”,并阅读一些开源的 Scala 项目源代码,这也会让你有所了解。

    最后,避免将来头疼的提示:消息类型应该始终是不可变的。所以你的ValidatedInput 应该是这样的:

    public class ValidatedInput
    {
        public readonly JArray Data { get; }
    
        public ValidatedInput(JArray data)
        {
            Data = data;
        }
    }
    

    或者更好:

    public class ValidatedInput
    {
        public readonly IReadOnlyList<JToken> Data { get; }
    
        public ValidatedInput(IReadOnlyList<JToken> data)
        {
            Data = data;
        }
    }
    

    希望这会有所帮助,祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-06
      • 1970-01-01
      • 2020-04-26
      • 1970-01-01
      相关资源
      最近更新 更多