有什么方法可以使Source可重用?
我有一个akka-http服务器,该服务器接收大文件上传,然后通过HTTP POST将(分块的)数据流传输到订户websocket和其他HTTP服务器。在这两种情况下,都有一个API可以接受Source [ByteString,Any]:
与采用单个ByteString的版本相比,使用这些API具有一些优势(仅需要执行单个HTTP发布,可以重新创建相同的分块消息等)。
那么有没有办法使这种工作(不将所有内容都缓存在内存中)?
val allSinks: Seq[Sink[Source[ByteString, Any], Future[Done]]] = ???
val g = RunnableGraph.fromGraph(GraphDSL.create(allSinks) { implicit builder => sinks =>
import GraphDSL.Implicits._
// Broadcast with an output for each subscriber
val broadcast = builder.add(Broadcast[DataSource](sinks.size))
Source.single(source) ~> broadcast
sinks.foreach(broadcast ~> _)
ClosedShape
})
答案 0 :(得分:0)
来源不可重用
不幸的是,Source
用尽后无法重用。数据的基础“源”可以重复使用以创建单独的Source
值,但每个值最多可以在一个流上运行。
持久性
如果需要重播功能,则需要将流式传输的数据存储在持久性机制中,以方便以后重播。这种机制可能是文件系统,数据库,Kafka,...
以下是使用文件系统的模型。
传入的POST
邮件正文可以以写模式流式传输到文件:
post {
path(Segment) { fileName =>
extractRequestEntity { entity =>
complete {
entity
.dataBytes
.toMat(FileIO.toPath(Paths.get(fileName), Set(CREATE_NEW, WRITE)))(Keep.Right)
.run()
.andThen {
case Success(ioResult) =>
StatusCodes.Ok -> s"wrote ${ioResult.count} bytes"
case Failure(ex) =>
StatusCodes.InternalServerError -> ex.toString
}
}
}
}
}
}
于是,您无需创建Broadcast
集线器,只需使用文件内容响应GET
请求:
path(Segment) { fileName =>
getFromFile(fileName)
}
利用以下事实:大多数操作系统将允许您以字节流的形式写入文件,同时以字节流的形式从文件中读取数据...