创建用于并行处理集合元素的Akka流

创建用于并行处理集合元素的Akka流,akka,akka-stream,Akka,Akka Stream,我试图为包含并行处理流的Akka流定义一个图(我使用的是Akka.NET,但这不重要)。设想一个订单数据源,每个订单由一个订单ID和一个产品列表(订单项)组成。工作流程如下: 接单 将订单广播到两个流,流A将处理订单项目,通道B将处理订单ID(一些簿记工作) 流程A:将订单项集合拆分为单独的元素,每个元素单独处理 流程A:对于前一步中拆分的每个订单项,调用一些外部服务,查找额外信息(价格、可用性等) 流程B:为给定的订单ID做一些额外的簿记 合并流A和B 将上一步骤中的合并数据发送到接收器,这将

我试图为包含并行处理流的Akka流定义一个图(我使用的是Akka.NET,但这不重要)。设想一个订单数据源,每个订单由一个订单ID和一个产品列表(订单项)组成。工作流程如下:

  • 接单
  • 将订单广播到两个流,流A将处理订单项目,通道B将处理订单ID(一些簿记工作)
  • 流程A:将订单项集合拆分为单独的元素,每个元素单独处理
  • 流程A:对于前一步中拆分的每个订单项,调用一些外部服务,查找额外信息(价格、可用性等)
  • 流程B:为给定的订单ID做一些额外的簿记
  • 合并流A和B
  • 将上一步骤中的合并数据发送到接收器,这将产生丰富的订单信息

  • 步骤1(Source.From)、2(Broadcast)、4-5(Map)、6(Merge)、7(Sink)看起来不错。但如何在Akka或反应流术语中实现集合拆分?这不是广播或展平,N个元素的集合需要拆分为N个独立的子流,这些子流稍后将合并回来。这是如何实现的?

    我建议在一个流程中完成。我知道两个流程看起来更酷,但相信我,就设计的简单性而言,这是不值得的(我尝试过)。你可以这样写

    import akka.stream.scaladsl.{Flow, Sink, Source, SubFlow}
    
    import scala.collection.immutable
    import scala.concurrent.Future
    
    case class Item()
    
    case class Order(items: List[Item])
    
    val flow = Flow[Order]
      .mapAsync(4) { order =>
        Future {
          // Enrich your order here
          order
        }
      }
      .mapConcat { order =>
        order.items.map(order -> _)
      }
      .mapAsync(4) { case (order, item) =>
        Future {
          // Enrich your item here
          order -> item
        }
      }
      .groupBy(2, tuple => tuple._1)
      .fold[Map[Order, List[Item]]](immutable.Map.empty) { case (map, (order, item)) => map.updated(order, map.getOrElse(order, Nil) :+ item) }
      .mapConcat { _.map { case (order, newItems) => order.copy(items = newItems)} }
    
    但即使是这种方法也不好。上面的代码或您的设计可能会出现很多问题。如果order的某个项目的扩展失败,您会怎么做?如果order对象的扩展失败怎么办?您的流会发生什么情况


    如果我是你,我会使用
    Flow[Order]
    并在
    mapsync
    中处理其子项,这样至少可以保证我没有部分处理的订单

    非常感谢你的回答。是的,mapAsync将提供高效且可预测的工作流。但我不确定我是否理解叉子的危险。是的,有些事情可能会出错,但如果在其中一个并发分支中发生错误,我是否能够以类似的方式处理错误?@VagifAbilov您可以处理它,但我认为需要更多代码来处理边缘情况和错误。更多代码->更难维护。在使用具有奇特拓扑结构的流构建系统之后,我意识到这通常是不值得的(以我的拙见)。我在另一次关于流的讨论中得到了类似的解释。有道理,谢谢你的澄清。