Example code:
public static void main(String[] args) throws Exception {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(1_000)
.setSocketTimeout(5_000)
.setConnectionRequestTimeout(60_000)
.build();
CloseableHttpClient httpClient = HttpClients.custom()
.disableAutomaticRetries()
.disableRedirectHandling()
.setDefaultRequestConfig(requestConfig)
.build();
HttpHead httpHead = new HttpHead("http://dns.google/a.mp4");
httpHead.setHeader("Accept-Encoding", "identity");
final long startTime = System.currentTimeMillis();
try (CloseableHttpResponse httpResponse = httpClient.execute(httpHead)) {
final long elapsedTime = System.currentTimeMillis() - startTime;
System.out.println("Success after " + elapsedTime + " ms");
} catch (Exception e) {
final long elapsedTime = System.currentTimeMillis() - startTime;
System.err.println("Error after " + elapsedTime + " ms");
e.printStackTrace();
}
}
This HttpHead is pointing to a URL that doesn't exist (http://dns.google/a.mp4 in this case), so this request should timeout after 1 second, right? But instead it's taking 2 seconds to timeout:
Error after 2064 ms
java.net.NoRouteToHostException: No route to host
at java.base/sun.nio.ch.Net.connect0(Native Method)
at java.base/sun.nio.ch.Net.connect(Net.java:579)
at java.base/sun.nio.ch.Net.connect(Net.java:568)
at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:593)
at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327)
at java.base/java.net.Socket.connect(Socket.java:633)
at org.apache.http.conn.socket.PlainConnectionSocketFactory.connectSocket(PlainConnectionSocketFactory.java:75)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
No matter what I change the ConnectTimeout to, it always takes 2x that amount of time to timeout. Why???
I'm using HttpClients version 4.5.13
So in the
DefaultHttpClientConnectionOperatorclass you’ll see this code:When you debug it, you'll see that this is the value of
addresses:So it’s actually making 4 requests... the first 2 fail with a
SocketTimeoutExceptionafter 1 second each, and the second 2 fail with aNoRouteToHostExceptionpretty much immediately. I don’t know why the last 2 requests fail immediately, but they do.So the end result is that it takes approximately 2 seconds to make all the requests, and the end result is a
NoRouteToHostException