【发布时间】:2019-04-19 19:26:19
【问题描述】:
我有两个服务,第一个是 frontend_service,第二个是 backend_service,我从 backend_service 获取大文件并尝试通过 frontend_service 转发给用户 response.getBodyAsStream() 但这会导致 frontend_service 中出现“java.lang.OutOfMemoryError:GC 开销限制超出”。
后端服务代码:
`
public static Result downloadLargeFile(String filePath){
File file = new File(filePath);
InputStream inputStream = new FileInputStream(file);
return ok(inputStream);
}
`
前端服务代码:
`
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);
}
);
}
`
我尝试了here 建议的解决方案,方法是从 inputStream 一次读取几个字节并在 frontend_service 中创建 tmp 文件并将 tmp 文件作为 frontend_service 的输出发送。
`
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 的文件。
【问题讨论】:
-
reading few bytes at a time from inputStream是我能想到的唯一解决方案。你能发布一下出了什么问题吗? -
我编辑了问题。
-
我怀疑是
return ok(tmpFile);导致了这个错误。你可以返回其他东西来测试这个理论吗? (可能是文件系统中的较小文件)。 -
感谢您的建议。我试过
ok("test")但同样的错误(java.lang.OutOfMemoryError)。看起来 inputStream 正在等待保存整个数据,而不是移动到下一个执行并将数据提供给 outputStream 以进行写入。
标签: java playframework playframework-2.3