Playframework BodyParser在游戏中表现如何!框架工作?

Playframework BodyParser在游戏中表现如何!框架工作?,playframework,akka-stream,akka-http,Playframework,Akka Stream,Akka Http,我有一个关于BodyParser.Raw的问题!框架说: 将主体解析为RawBuffer。这将尝试存储实体 在内存中,最大为播放配置的内存缓冲区大小,但回退到 如果超过该值,则将其写入文件 我很难理解上面的描述。这是否意味着:- 如果我将以下配置放入我的application.conf文件: play.http.parser.maxMemoryBuffer=128k play.http.parser.maxDiskBuffer=1G 并说我的请求体有15MB大小,然后播放!是否从请求正文中读取

我有一个关于
BodyParser.Raw的问题!框架说:

将主体解析为
RawBuffer
。这将尝试存储实体 在内存中,最大为播放配置的内存缓冲区大小,但回退到 如果超过该值,则将其写入文件

我很难理解上面的描述。这是否意味着:-

如果我将以下配置放入我的
application.conf
文件:

play.http.parser.maxMemoryBuffer=128k
play.http.parser.maxDiskBuffer=1G
并说我的请求体有15MB大小,然后播放!是否从请求正文中读取/解析前128k,将其写入文件,然后从请求正文中流式传输/解析下一个128k,将其写入同一个文件,…,直到15MB请求正文被完全解析?这意味着我们只使用128k内存,并且我们能够处理大小为15MB的请求体

我知道这听起来好得难以置信

有人能解释一下吗

更新

如果有人在这里遇到同样的问题,我想在这里添加一些更新。因此@Ivan Kurchenko是正确的(见下面他的答案):
BodyParser.Raw
可用于
POST
比配置的
play.http.parser.maxMemoryBuffer
更大的请求体。玩在这种情况下,将使用磁盘缓冲请求。换句话说,您可以
POST
一个比JVM中可用内存更大的大请求体

我使用Chrome(还有Firefox)测试失败的原因是我默认启用了CSRF过滤器。一旦我禁用它,一切正常。例如,以下配置

play.http.parser.maxMemoryBuffer=1k
play.http.parser.maxDiskBuffer=4G
play.filters.disabled+=play.filters.csrf.CSRFFilter

表示如果请求正文大于1k,则播放!将使用您的磁盘缓冲您的请求(当然,我禁用了CSRF筛选器)。现在,通过这种配置,我可以成功上传一部超过3G大小的电影。因此,如果需要处理大型请求,可以使用
BodyParser.Raw
。嗯

不是真的-如果请求大小超过内存阈值,则在配置为
play.http.parser.maxMemoryBuffer=128k的情况下,整个请求正文将写入临时文件,否则将写入内存。然后,对于下一个解析,主体也将从文件或内存流式传输。
让我们一起来看看:

-在内部创建
RawBuffer
,例如这里

以及我们感兴趣的两种方法: -它接受传入字节,总大小超过缓冲区大小执行
backToTemporaryFile
——这意味着将所有请求写入临时文件

  @volatile private var inMemory: ByteString                 = initialData
  @volatile private var backedByTemporaryFile: TemporaryFile = _
  @volatile private var outStream: OutputStream              = _

  private[play] def push(chunk: ByteString): Unit = {
    if (inMemory != null) { //checks whether current in memory buffer exists

      //if next readed chunk of request body exceeds in memory buffer size
      if (chunk.length + inMemory.size > memoryThreshold) {
        backToTemporaryFile()  // create temporary file
        outStream.write(chunk.toArray)// write buffer to temporary file
      } else {
        inMemory = inMemory ++ chunk // append in memory buffer with next chunk
      }
    } else {
      outStream.write(chunk.toArray) // append in memory buffer with next chunk
    }
  }
然后-如果内存缓冲区中存在,它自己读取字节。或者从临时文件中读取字节

  @volatile private var inMemory: ByteString                 = initialData
  @volatile private var backedByTemporaryFile: TemporaryFile = _
  @volatile private var outStream: OutputStream              = _

  private[play] def push(chunk: ByteString): Unit = {
    if (inMemory != null) { //checks whether current in memory buffer exists

      //if next readed chunk of request body exceeds in memory buffer size
      if (chunk.length + inMemory.size > memoryThreshold) {
        backToTemporaryFile()  // create temporary file
        outStream.write(chunk.toArray)// write buffer to temporary file
      } else {
        inMemory = inMemory ++ chunk // append in memory buffer with next chunk
      }
    } else {
      outStream.write(chunk.toArray) // append in memory buffer with next chunk
    }
  }

另请注意:如果传入的请求正文大小超过了
play.http.parser.maxDiskBuffer中的配置值,则play将以413-请求实体太大状态进行响应。

Hi@Ivan,感谢您的解释!你指出的阅读方法确实有帮助。还有几件事:首先,在我的例子中,配置的内存阈值是
play…maxmorybuffer=128k
play…maxmdiskbuffer=1G
是硬盘缓冲区大小。。。所以我猜你的回答有误?其次,我写了一个小应用程序来测试这个,为了模拟一个大的请求体,我上传了一个大文件。现在,如果将“play….maxMemoryBuffer”配置为<文件大小,Chrome会立即返回“无法访问此站点”,似乎您在回答中描述的逻辑从未触发过???@lee非常感谢您关注细节,是的,你是对的,这是一个输入错误,我还添加了一些注释的代码片段。@lee我不确定Chrome-为了测试这种低级的东西,我更喜欢使用合适的工具,如Postman或curl,它们可以提供更多HTTP低级的细节。@lee我更新了关于大小限制的答案。@lee我不确定rest Play!解析器-需要单独查看。但是,有些代码只存储在内存中,比如Json或字符串。