Answering my own question:
Do not try to retry the HTTP request. To do this, you will be forced to buffer an InputStream for all requests, even if a deadlock never occurs. This will allow you to refuse denial of service attacks if you are forced to accept large downloads.
Instead, I recommend this approach: Is it appropriate to return HTTP 503 in response to a database lock?
You can then break large downloads into multiple requests stitched together using AJAX. Not really, but it works, and overall your design should be easier to implement.
UPDATE . According to Brett Wooldridge :
You need a small pool of several dozen connections in most cases, and you want the rest of the application threads to be blocked in the pool waiting for the connection.
Just as Hikari recommends a small number of threads with a long queue of requests, I believe this is true for the web server. By limiting the number of active streams, we limit the number of input streams that we need to buffer (other requests are blocked before sending the HTTP body).
To further strengthen this point, Craig Ringer recommends recovering from server-side failures where possible.
source share