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

时间:2013-12-23 15:03:52

标签: playframework inputstream enumerator

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

我有一个InputStream,所以最明显的事情是将Ok.chunked与Enumerator.fromStream()一起使用,但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.

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

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

1 个答案:

答案 0 :(得分:1)

我实际上在某种程度上误读了文档。 Enumerator.fromStream有一个隐含的ExecutionContext,你可以提供 如果为此特定类型的操作创建专用上下文,您仍然可以遇到线程饥饿,但您可以控制哪个线程池可以解决该问题。

我们正在玩游戏!所以我们可以在application.conf中配置akka threadpool:

# 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
    }
  }
}

并在代码中使用它们:

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

...

Enumerator.fromStream(stream)(MyContexts.s3Streaming)