如何创建具有背压和控制的Akka流

时间:2018-01-17 08:45:01

标签: scala akka-stream backpressure

我需要使用以下界面创建一个函数:

import akka.kafka.scaladsl.Consumer.Control

object ItemConversionFlow {

def build(config: StreamConfig): Flow[Item, OtherItem, Control] = {
    // Implementation goes here
}

我的问题是我不知道如何以适合上述界面的方式定义流程。

当我做这样的事情时

val flow = Flow[Item]
    .map(item => doConversion(item)
    .filter(_.isDefined)
    .map(_.get)

结果类型是Flow [Item,OtherItem,NotUsed]。到目前为止,我还没有在Akka文档中找到一些东西。此外,akka.stream.scaladsl.Flow上的函数仅提供“NotUsed”而不是Control。如果有人能指出我正确的方向,那就太棒了。

一些背景知识:我需要设置几个仅在转换部分中区分的管道。这些管道是主流的子流,可能由于某种原因而停止(相应的消息到达某个kafka主题)。因此我需要控制部分。我的想法是创建一个Graph模板,我只需将上述流作为参数插入(工厂返回它)。对于特定情况,我们有一个有效的解决方案。为了概括它,我需要这种流程。

1 个答案:

答案 0 :(得分:0)

你实际上有背压。但是,想想你对背压真正需要什么......例如,你没有使用异步阶段来提高吞吐量...... Backpressure避免了快速生产者过度生长的嫌疑人https://doc.akka.io/docs/akka/2.5/stream/stream-rate.html。在您的示例中不用担心,您的流将根据 doConversion 完成的时间长度向发布者请求新元素。

如果您想获取流的结果,请使用toMat或viaMat。例如,如果您的流发出Item并将其转换为OtherItem:

val str = Source.fromIterator(() => List(Item(Some(1))).toIterator)
  .map(item => doConversion(item))
  .filter(_.isDefined)
  .map(_.get)
  .toMat(Sink.fold(List[OtherItem]())((a, b) => {
      // Examine the result of your stream
      b :: a
    }))(Keep.right)
  .run()

str将是Future [List [OtherItem]]。试着根据你的情况推断这个。

或者使用toMat with KillSwitches,“创建一个[[FlowShape]]的新[[Graph]],它实现了一个允许外部完成的外部开关    *独特的物化。不同的实现会产生不同的独立开关。“

  def build(config: StreamConfig): Flow[Item, OtherItem, UniqueKillSwitch] = {
    Flow[Item]
      .map(item => doConversion(item))
      .filter(_.isDefined)
      .map(_.get)
      .viaMat(KillSwitches.single)(Keep.right)
  }


  val stream = 
    Source.fromIterator(() => List(Item(Some(1))).toIterator)
    .viaMat(build(StreamConfig(1)))(Keep.right)
    .toMat(Sink.ignore)(Keep.both).run

  // This stops the stream
  stream._1.shutdown()

  // When it finishes
  stream._2 onComplete(_ => println("Done"))