I have an issue in my application using Spring's RestTemplate configured with Apache HttpClient 5 as the underlying httpclient. My application is calling a downstream legacy system, and while that system is "down" for maintenance, it still accepts connections (TLS handshake and all), but never returns a response.
The problem I'm having is when I set the request timeout at 8 seconds on the Apache client, requests sent to this downstream service are blocking for double that timeout setting (16 seconds).
I have this isolated to the Apache HttpClient, and have reproduced this behavior in a unit test using self-signed certs. Since the code necessary to reproduce is too long to post here, I have a repository with the test reproducing the issue here: apache-httpclient-socket-timeout-test
You can see in the following logs that the read timeout does happen after the configured 8 seconds, but it is blocking for an additional 8 seconds to close the connection. This doesn't happen using HTTP, only HTTPS.
14:45:21.587 [main] DEBUG org.apache.hc.client5.http.wire -- http-outgoing-1 >> "[\r][\n]"14:45:29.589 [main] DEBUG org.apache.hc.client5.http.wire -- http-outgoing-1 << "[read] I/O error: Read timed out"14:45:29.589 [main] DEBUG o.a.h.c.h.i.i.DefaultManagedHttpClientConnection -- http-outgoing-1 Close connection14:45:37.591 [main] DEBUG o.a.h.c.h.i.c.InternalHttpClient -- InternalConnectionEndpoint-7eb6b6b6 endpoint closed
Before I submit this as a bug to Apache, I am posting here to see if anyone else has run into this issue - maybe something is off in my configuration?
To reduce the variable that this is a server issue, I've added a test that sends a request using plain http and also a test that sends a TLS request using the JDK HttpClient, and both adhere to the requestTimeout that I've set. However, I connected this test to a non-java (node-js mock application), and could not reproduce...
So perhaps, this is a java socket issue - but, I've tested this in several JVM implementations and had the same results.