当返回 minio 流作为 spring ResponseEntity 时,如何摆脱 okhttp3 "A connection to ... was was leaked" 警告?
How do I get rid of okhttp3 "A connection to ... was was leaked" warning when returning a minio stream as spring ResponseEntity?
我正在使用 minio 读取一个文件,并且有一个 REST 控制器,returns minio 作为 InputStreamResource 给出的输入流。这是我的代码:
@GetMapping("/download")
fun download(): ResponseEntity<InputStreamResource> {
// read file from minio
// getObjectResponse is an InputStream
...
val getObjectResponse = minioClient.getObject(getObjectArgs)
return ResponseEntity.ok().body(InputStreamResource(getObjectResponse))
}
根据 将 InputStream 包装到 InputStreamResource 中是正确的,并且 spring 应该在传递响应后关闭底层 InputStream。然而我还是得到了臭名昭著的
okhttp3.OkHttpClient: A connection to ... was leaked. Did you forget to close a response body?
我在这里有哪些选择?我宁愿不需要将 minio 内容复制和缓冲到内存中,因为这些文件往往非常大。
只要您关闭 Response、ResponseBody 或像 ResponseBody.inputStream() 这样的流中的任何一个,OkHttp 响应就会被清除。
您依赖于接受您的 InputStreamResource 的调用方才能正确关闭它。
我建议 wrapping/decorating 您传递给 InputStreamResource 的输入流并记录调用何时何地关闭。
通过使用 Yuri Schimkes 的建议来改进日志记录和一些调试,我发现 spring 仅在返回 HTTP 200 时关闭输入流 并且输入流是实际阅读并交付。在我的例子中,有时会发生缓存(spring 使用 etags 的魔法)并且 spring 返回 HTTP 304 而没有消耗和关闭输入流。
我正在使用 minio 读取一个文件,并且有一个 REST 控制器,returns minio 作为 InputStreamResource 给出的输入流。这是我的代码:
@GetMapping("/download")
fun download(): ResponseEntity<InputStreamResource> {
// read file from minio
// getObjectResponse is an InputStream
...
val getObjectResponse = minioClient.getObject(getObjectArgs)
return ResponseEntity.ok().body(InputStreamResource(getObjectResponse))
}
根据
okhttp3.OkHttpClient: A connection to ... was leaked. Did you forget to close a response body?
我在这里有哪些选择?我宁愿不需要将 minio 内容复制和缓冲到内存中,因为这些文件往往非常大。
只要您关闭 Response、ResponseBody 或像 ResponseBody.inputStream() 这样的流中的任何一个,OkHttp 响应就会被清除。
您依赖于接受您的 InputStreamResource 的调用方才能正确关闭它。
我建议 wrapping/decorating 您传递给 InputStreamResource 的输入流并记录调用何时何地关闭。
通过使用 Yuri Schimkes 的建议来改进日志记录和一些调试,我发现 spring 仅在返回 HTTP 200 时关闭输入流 并且输入流是实际阅读并交付。在我的例子中,有时会发生缓存(spring 使用 etags 的魔法)并且 spring 返回 HTTP 304 而没有消耗和关闭输入流。