将Akka HTTP连接到Akka流

时间:2017-02-27 11:23:05

标签: akka akka-stream akka-http

我想用Akka HTTP构建一个REST服务,连接到现有的Sink(使用Kafka反应流),但我无法弄清楚如何将HTTP流链接到Akka流接收器......

我应该选择使用Flows的低级Akka HTTP API吗?

我的要求是:

  • 完整流程的背压
  • 当kafka sink确认所有事件时的200响应代码
  • 当背压太高时
  • 500?可能吗 ?

这是我的代码当前代码

// flow to split group of lines into lines
  val splitLines = Flow[String].mapConcat(_.split("\n").toList)

// sink to produce kafka records in kafka
val kafkaSink = Flow[String]
    .map(new ProducerRecord[Array[Byte], String](topic, _))
    .toMat(Producer.plainSink(ProducerSettings(system,new ByteArraySerializer, new StringSerializer)))(Keep.right)

val routes = {
    path("ingest") {
      post {
        logger.info("starting ingestion")
        entity(as[GenericEvent]) { eventIngest =>
          ????      
        }~
        entity(as[GenericEventList]) { eventIngestList =>
          ????
        }
      }
    }
  }

Http(actorSystem).bindAndHandle(routes, config.httpInterface, config.httpPort)

1 个答案:

答案 0 :(得分:2)

有几种方法可以解决这个问题。一个建议可能是将数据直接从您的请求实体流式传输到您的kafka接收器。 extractDataBytes指令可帮助您完成该操作(更多信息here)。

尝试以下示例中的内容。我添加了一个???流,以允许您的特定于案例的转换正确地拆分/转换您的请求实体字节。您可以使用Framing.delimiter之类的内容来拆分实体字节流(更多信息here)。

  (extractDataBytes & extractMaterializer) { (byteSrc, mat) =>
    val f = byteSrc.via(???).runWith(kafkaSink)(mat)
    onComplete(f){
      case Success(value) => complete(s"OK")
      case Failure(ex)    => complete((StatusCodes.InternalServerError, s"An error occurred: ${ex.getMessage}"))
    }
  }

或者,如果要将实体解组为某个域对象,可以执行类似

的操作
  (entity(as[Event]) & extractMaterializer) { (event, mat) =>
    val f = Source.single(event).via(???).runWith(kafkaSink)(mat)
    onComplete(f){
      case Success(value) => complete(s"OK")
      case Failure(ex)    => complete((StatusCodes.InternalServerError, s"An error occurred: ${ex.getMessage}"))
    }
  }

要回答你的最后一个问题,如果Kafka背压,你的流将永远不会完成。您应该期望服务器在配置的请求超时后返回500(引用下面的文档):

  

默认请求超时全局应用于所有路由,可以是   使用akka.http.server.request-timeout设置进行配置(其中   默认为20秒)。