Scala 在Akka Http中从源向元素发送元素

Scala 在Akka Http中从源向元素发送元素,scala,akka,akka-stream,akka-http,Scala,Akka,Akka Stream,Akka Http,我正在使用Akka Http和Akka Streams开发一个客户机-服务器应用程序。 其主要思想是服务器必须向http响应提供来自Akka streams的源 问题是服务器在向客户端发送第一条消息之前积累了一些元素。但是,我需要服务器在源代码生成新元素后立即向元素发送元素 代码示例: case class Example(id: Long, txt: String, number: Double) object MyJsonProtocol extends SprayJsonSupport

我正在使用Akka Http和Akka Streams开发一个客户机-服务器应用程序。 其主要思想是服务器必须向http响应提供来自Akka streams的源

问题是服务器在向客户端发送第一条消息之前积累了一些元素。但是,我需要服务器在源代码生成新元素后立即向元素发送元素

代码示例:

case class Example(id: Long, txt: String, number: Double)

object MyJsonProtocol extends SprayJsonSupport with DefaultJsonProtocol {
  implicit val exampleFormat = jsonFormat3(Test)
}

class BatchIterator(batchSize: Int, numberOfBatches: Int, pause: FiniteDuration) extends Iterator[Array[Test]]{

  val range = Range(0, batchSize*numberOfBatches).toIterator
  val numberOfBatchesIter = Range(0, numberOfBatches).toIterator

  override def hasNext: Boolean = range.hasNext

  override def next(): Array[Test] = {
    println(s"Sleeping for ${pause.toMillis} ms")
    Thread.sleep(pause.toMillis)
    println(s"Taking $batchSize elements")
    Range(0, batchSize).map{ _ =>
      val count = range.next()
      Test(count, s"Text$count", count*0.5)
    }.toArray
  }
}

object Server extends App {
  import MyJsonProtocol._
  implicit val jsonStreamingSupport: JsonEntityStreamingSupport = EntityStreamingSupport.json()
      .withFramingRenderer(
        Flow[ByteString].intersperse(ByteString(System.lineSeparator))
      )

  implicit val system = ActorSystem("api")
  implicit val materializer = ActorMaterializer()
  implicit val executionContext = system.dispatcher

  def fetchExamples(): Source[Array[Test], NotUsed] = Source.fromIterator(() => new BatchIterator(5, 5, 2 seconds))

  val route =
    path("example") {
      complete(fetchExamples)
    }

  val bindingFuture = Http().bindAndHandle(route, "localhost", 9090)
  println("Server started at localhost:9090")
  StdIn.readLine()
  bindingFuture.flatMap(_.unbind()).onComplete(_ ⇒ system.terminate())
}
然后,如果我执行:

curl --no-buffer localhost:9090/example
我同时获取所有元素,而不是每2秒接收一个元素


知道如何强制服务器发送源代码中的每个元素吗?

最后,我找到了解决方案。问题是源是同步的。。。因此,解决方案就是调用函数async


如果正确理解这一点,您希望服务器对单个请求发送多个响应。这不是HTTP所支持的东西——为此,您需要类似websocket的东西。有一些关于Akka-HTTP中WebSocket支持的详细信息。谢谢@Astrid的建议。顺便说一句,我找到了另一种选择,一个HTTP请求可以用多个响应来响应:
complete(fetchExamples.async)