Play框架用大体转发请求/响应

问题描述 投票:0回答:1

我正在使用 play 框架将请求转发到一些内部服务。其中一项服务返回相当大的有效负载(5MB json 数据)。当我直接调用服务时,大约需要 5 秒来处理和返回请求(正在进行一些处理)。当我使用 play 转发请求并返回响应时,需要花费 3 倍的时间。我还得到了一些

java.lang.OutOfMemoryError: Java heap space at play.shaded.ahc.org.asynchttpclient.netty.NettyResponse.getResponseBodyAsByteBuffer
错误,这些错误怀疑来自于解析 json 主体,这是不必要的。有没有办法转发请求并返回响应而不解析它?

目前我的代码如下所示:

def process = Authorized().async { request =>
  request.body.asJson.map { body =>
    ws.url("internal-service/process")
      .addHttpHeaders("Accept-Encoding" -> "gzip, deflate")
      .post(body).map { res =>
      if (res.status >= 200 && res.status < 300) {
        Ok(res.json)
      } else {
        throw SimpleServiceException(s"Failed to process datasets. Reason ${res.status}: ${res.body}")
      }
    }
  }.getOrElse(Future.successful(BadRequest))
}
scala playframework
1个回答
0
投票

首先,让我们了解导致代码中出现问题的原因。

当您调用

res.json
时,您是在告诉 Play 消耗整个响应,将其解析为 JSON,将其保留在内存中,然后才能将其发送回来。

这不是你想做的事。

相反,您可以将响应解析为

Source
(Akka Stream),以便延迟/渐进地使用它。

做这样的事情:

val response = ws.url(...).withMethod("POST").stream()
val bodyStream = response.map(_.bodyAsSource())
bodyStream.map(Ok.chunked)
© www.soinside.com 2019 - 2024. All rights reserved.