大文件下载导致超出GC开销限制

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

我有两个服务,第一个是frontend_service,第二个是backend_service,我从backend_service获取大文件,并尝试使用response.getBodyAsStream()通过frontend_service转发给用户,但这导致“java.lang.OutOfMemoryError:GC开销超出限制” frontend_service。

backend_service的代码:

`

public static Result downloadLargeFile(String filePath){
   File file = new File(filePath);
   InputStream inputStream = new FileInputStream(file);
   return ok(inputStream);
}

`

frontend_service的代码:

`

  public static F.Promise<Result> downloadLargeFile(String filePath) {
       //this will call backend_service downloadLargeFile method.
       String backEndUrl = getBackEndUrl(filePath);
       return getInputStream(backEndUrl);
    }

`

`

public static Promise<Result> getInputStream(String url) {
            return WS.url(url).get().map(
                    response -> {
                        InputStream inputStream =  response.getBodyAsStream();
                        return ok(inputStream);
                    }
            );
}

`

我尝试通过从inputStream一次读取几个字节并在frontend_service中创建tmp文件并将tmp文件作为frontend_service的输出发送来建议here解决方案。

`

    public static Promise<Result> getInputStream(String url) {
            return WS.url(url).get().map(
                    response -> {
                        InputStream inputStream = null;
                        OutputStream outputStream = null;
                        try {
                            inputStream =  response.getBodyAsStream();
                            //write input stream to tmp file
                            final File tmpFile = new File("/tmp/tmp.txt");
                            outputStream = new FileOutputStream(tmpFile);

                            int read = 0;
                            byte[] buffer = new byte[500];
                            while((read = inputStream.read(buffer)) != -1){
                                outputStream.write(buffer, 0 , read);
                            }
                            return ok(tmpFile);
                        } catch (IOException e) {
                            e.printStackTrace();
                            return badRequest();
                        } finally {
                            if (inputStream != null) {inputStream.close();}
                            if (outputStream != null) {outputStream.close();}
                        }
                    }
            );

`

上面的代码也抛出了java.lang.OutOfMemoryError。我正在尝试1 GB文件。

java playframework playframework-2.3
1个回答
0
投票

我没有“手下”的实现,所以我将编写算法。

1.游戏使用AsyncHttpClient下的WS。您需要获取它,或按照https://www.playframework.com/documentation/2.3.x/JavaWS#Using-WSClient中的描述创建它

2.然后,你需要实现AsyncCompletionHandler,就像类https://static.javadoc.io/org.asynchttpclient/async-http-client/2.0.0/org/asynchttpclient/AsyncHttpClient.html的描述一样

3.在onBodyPartReceived类的AsyncCompletionHandler方法中,你需要将身体部分推到分块的游戏响应中。这里描述的反应:https://www.playframework.com/documentation/2.3.x/JavaStream#Chunked-responses

附:

讨论类似的解决方案,但方向相反 - 通过“前端”(播放2)服务上传到“后端”(亚马逊)服务:qazxsw poi

© www.soinside.com 2019 - 2024. All rights reserved.