简体   繁体   English

Akka流 - 失败后用广播和zip恢复图形

[英]Akka streams - resuming graph with broadcast and zip after failure

I have a flow graph with broadcast and zip inside. 我有一个内置广播和拉链的流程图。 If something (regardless what is it) fails inside this flow, I'd like to drop the problematic element passed to it and resume. 如果某个东西(无论它是什么)在这个流程中失败了,我想删除传递给它的有问题的元素并恢复。 I came up with the following solution: 我提出了以下解决方案:

val flow = Flow.fromGraph(GraphDSL.create() { implicit builder =>
  import GraphDSL.Implicits._

  val dangerousFlow = Flow[Int].map {
    case 5 => throw new RuntimeException("BOOM!")
    case x => x
  }
  val safeFlow = Flow[Int]
  val bcast = builder.add(Broadcast[Int](2))
  val zip = builder.add(Zip[Int, Int])

  bcast ~> dangerousFlow ~> zip.in0
  bcast ~> safeFlow ~> zip.in1

  FlowShape(bcast.in, zip.out)
})

Source(1 to 9)
  .via(flow)
  .withAttributes(ActorAttributes.supervisionStrategy(Supervision.restartingDecider))
  .runWith(Sink.foreach(println))

I'd expect it to print: 我希望它能打印出来:

(1,1)
(2,2)
(3,3)
(4,4)
(5,5)
(6,6)
(7,7)
(8,8)
(9,9)

However, it deadlocks, printing only: 但是,它只会出现死锁,只能打印:

(1,1)
(2,2)
(3,3)
(4,4)

We've done some debugging, and it turns out it applied the "resume" strategy to its children, which caused dangerousFlow to resume after failure and thus to demand an element from bcast . 我们已经做了一些调试,结果发现它将“恢复”策略应用于其子bcast ,这导致dangerousFlow的流程在失败后恢复,从而要求bcast的元素。 bcast won't emit an element until safeFlow demands another element, which actually never happens (because it's waiting for demand from zip ). bcast不会发出一个元素,直到safeFlow要求另一个元素,实际上从未发生(因为它正在等待来自zip需求)。

Is there a way to resume the graph regardless of what went wrong inside one of the stages? 有没有办法恢复图表,无论其中一个阶段内出了什么问题?

I think you understood the problem well. 我认为你很好地理解了这个问题。 You saw that, when your element 5 crashes dangerousFlow , you should also stop the element 5 that is going through safeFlow because if it reaches the zip stage, you have the problem you describe. 您看到,当您的元素5崩溃dangerousFlow ,您还应该停止正在通过safeFlow的元素5 ,因为如果它到达zip阶段,则会出现您描述的问题。 I don't know how to solve your problem between the broadcast and zip stages, but what about pushing the problem further, where it is easier to handle? 我不知道如何在broadcastzip阶段之间解决你的问题,但是如何进一步推动问题,哪里更容易处理?

Consider using the following dangerousFlow : 考虑使用以下dangerousFlow

import scala.util._
val dangerousFlow = Flow[Int].map {
  case 5 => Failure(new RuntimeException("BOOM!"))
  case x => Success(x)
}

Even in case of problem, dangerousFlow would still emit data. 即使出现问题, dangerousFlow仍会发出数据。 You can then zip as you are currently doing and would just need to add a collect stage as last step of your graph. 然后,您可以按照当前的方式进行zip ,只需添加一个collect阶段作为图表的最后一步。 On a flow, this would look like: 在流程上,这看起来像:

Flow[(Try[Int], Int)].collect {
  case (Success(s), i) => s -> i
}

Now if, as you wrote, you really expect it to output the (5, 5) tuple, use the following: 现在,如果你正如你所写,你真的希望它输出(5, 5)元组,请使用以下内容:

Flow[(Try[Int], Int)].collect {
  case (Success(s), i) => s -> i
  case (_, i)          => i -> i
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM