Play Framework [2.2-scala]:从缓慢的InputStream创建Enumerator

Jaa*_*aap 5 inputstream enumerator playframework

我正在实施AWS S3文件传递API.我被迫将S3的S3ObjectInputStream中的字节流式传输到浏览器.我们有一个用例用云端服务文件不是一个选项(主要是本地开发)

我有一个InputStream,所以最明显的事情是使用带有Enumerator.fromStream()的Ok.chunked,但Enumerator.fromStream()有一个非常明确的警告,即流不应该很慢.我假设AWS S3ObjectInputStream可能是最慢的流之一.

http://www.playframework.com/documentation/2.2.x/api/scala/index.html#play.api.libs.iteratee.Enumerator$

def fromStream(input: InputStream, chunkSize: Int = 1024 * 8)
              (implicit ec: ExecutionContext): Enumerator[Array[Byte]]

Create an enumerator from the given input stream.

This enumerator will block on reading the input stream, in the default iteratee
thread pool. Care must therefore be taken to ensure that this isn't a 
slow stream. If using this with slow input streams, consider setting the value
of iteratee-threadpool-size to a value appropriate for handling the blocking.
Run Code Online (Sandbox Code Playgroud)

所以我想知道最安全的方法是避免线程饥饿并将文件流式传输到浏览器而不将整个文件保存在内存中.

是否有其他方法可以从InputStream获取枚举器(或我们可以在结果中发送的内容)?

Jaa*_*aap 1

我实际上以某种方式误读了文档。Enumerator.fromStream 有一个您可以提供的隐式 ExecutionContext。
如果您为这种特定类型的操作创建专用上下文,您仍然可能会遇到线程匮乏的情况,但您可以控制哪个线程池遇到该问题。

我们用的是游戏!所以我们可以在 application.conf 中配置 akka 线程池:

# this is a root value in the application.conf, but you can put it anywhere
# as long as you provide the full path to the .lookup() function
my-contexts {
  s3-streaming {
    fork-join-executor {
      parallelism-min = 50
      parallelism-max = 50
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

并在代码中使用它们,如下所示:

object MyContexts {
  val s3Streaming: ExecutionContext = 
    Akka.system.dispatchers.lookup("my-contexts.s3-streaming")
}

...

Enumerator.fromStream(stream)(MyContexts.s3Streaming)
Run Code Online (Sandbox Code Playgroud)