I’ve went through all the answers for this question
download a file from Spring boot rest service, realizing that the differences are related to the return value. Basically, there are two type families.
- Return type for Blocking Servlet
ResponseEntity<Resource>
ResponseEntity<InputStreamResource>
ResponseEntity<ByteArrayResource>
ResponseEntity<FileSystemResource>
- Return type for Async Servlet(Servlet >= 3.0)
- 2.1)
DeferredResult<ResponseEntity<?>>
- 2.2)
ResponseBodyEmitter
orResponseEntity<ResponseBodyEmitter>
- 2.3)
SseEmitter
orResponseEntity<SseEmitter>
- 2.4)
StreamingResponseBody
orResponseEntity<StreamingResponseBody>
Someone mentions that, for downloading big files, it might go OOM if we use ByteArrayResource
.
IIUC, either FileSystemResource
or StreamingResponseBody
is friendly with big files, with http chunked encoding
under the hood.
FileSystemResource
servlet container thread is blocked but can take advantage ofZero Copy
. More efficient for memory.StreamingResponseBody
servlet container thread is released. More efficient for CPU.
If that’s true, will it be the best choice to use DeferredResult<ResponseEntity<FileSystemResource>>
instead, since it’s more efficient for both memory and CPU?
P.S. Let’s ignore CDN and some other tech like BitTorrent for downloading big files in real world, and focus on comparing among these 3 ways(FileSystemResource
/StreamingResponseBody
/DeferredResult<ResponseEntity<FileSystemResource>>
).
3
As others have mentioned in the comments it all depends on the file size. But there’s not only a CPU/resource but also a connection timeout aspect.
What you are essentially doing is putting the connection on hold until the server has prepared the response.
Unless you have some hearbeat mechanism in action (which is not the default for HTTP/TCP), for any other party a connection on hold is indistinguishable from a server failure or connection drop. Indeed if your “blocking” is too long, intermediate gateways may assume the connection dead/timeout and drop it.
In my experience blocking the HTTP response is somewhat acceptable if you can guarantee a delay below 30 seconds. Above 30 seconds things become unreliable. That’s not just annecdotal, but from experience I’ve made while writing this long-poll library.