我有以下代码作为S3存储桶的网关。这样做的目的是下载位于S3上的文件但不暴露S3项链接。
一切正常,但在大约50次下载后,我们不断获得Timeout waiting for connection from pool
例外。
我发现这可能是由于没有关闭s3Object.getObjectContent()
造成的,但正如您可以看到我正在使用"尝试使用资源"这可确保调用close()
。我不仅要在流上做这个,还要对对象本身这样做。这是最后的手段,因为它不会改变任何东西。事实上,S3Object.close()做同样的事情 - 关闭底层的InputStream。
当我手动测试时,我可以看到正在调用close()
。
@GET
@Produces({MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_JSON})
@Path("/{id}/download")
public Response download(@NotNull @PathParam("id") String id) {
return repository.get()
.map(record -> Response.status(OK)
.header(HttpHeaders.CONTENT_DISPOSITION, "...")
.entity((StreamingOutput) outputStream -> {
try (S3Object s3Object = s3Service.getObject(record.getS3Key());
InputStream inputStream = s3Object.getObjectContent()) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
outputStream.flush();
}
outputStream.flush();
}
})
.build())
.orElseThrow(() -> new EntityNotFoundException(String.format("Could not find download id: %s", id)));
}
[编辑]
答案 0 :(得分:1)
似乎您必须在关闭流is.skip(Long.MAX_VALUE)
之前对其进行调用。
try (InputStream is =new DrainOnCloseInputStream(s3Object.getObjectContent())) {
processFile(is,fileExt, context, logGroupName, logStreamName);
}
public class DrainOnCloseInputStream extends FilterInputStream {
public DrainOnCloseInputStream(InputStream paramInputStream) {
super(paramInputStream);
}
@Override
public void close() throws IOException {
drain(in);
super.close();
}
private static void drain(InputStream is) throws IOException {
is.skip(Long.MAX_VALUE);
}
}