2013-12-23 35 views
4

我正在实现AWS S3文件传输API。我被迫把S3的S3ObjectInputStream中的字节流到浏览器。 我们有一个使用cloudfront服务的文件不是一个选项(主要是本地开发)Play Framework [2.2-scala]:从缓慢的InputStream创建枚举器

我有一个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获得一个枚举器(或者我们可以在一个Result中发送的东西)?

+0

另一种使用情况是自定义授权在S3中的对象,那么你需要流式传输字节... – Jaap

+0

也许你可以使用unfoldM? –

+0

您是否找到任何解决方案? – nachokk

回答

1

我实际上有些误读文档。 Enumerator.fromStream具有您可以提供的隐式ExecutionContext。
如果您为此特定类型的操作创建专用上下文,则仍然可能遇到线程匮乏,但是您控制哪个线程池可以解决该问题。

我们正在使用玩!因此,我们可以只配置阿卡的线程池在我们application.conf:

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