While looking into an issue in the Quarkus project, it has been observed
that the Apache HTTP client library (4.5.13 version) behaves differently
against Java 11 and Java 16 when it comes to HTTP request retries. The
initial issue that triggered this investigation is explained here[1].
As noted in that comment, the Apache HTTP client library has a
"RetryExec" which uses a "HttpRequestRetryHandler" implementation to
decide whether to retry an request which failed. The default
implementation of "HttpRequestRetryHandler" is the
"DefaultHttpRequestRetryHandler" which among other things, uses a
collection of exception types to decide which requests shouldn't be
retried. One such exception type is "java.net.ConnectException" for
which request won't be retried.
What's happening now is that, in Java 11 the call to
java.net.Socket.connect(addr, timeout) was leading to a
"ConnectException" in certain cases. That same call now throws a
"java.net.NoRouteToHostException" starting Java 13+. As a result, a
request against the same host/port in Java 11 doesn't trigger a request
retry (because it throws ConnectException) whereas the same request
triggers a retry in Java 16 (because it throws NoRouteToHostException).
The issue of the same Socket.connect(...) API returning different
exception types was raised in the OpenJDK mailing list here[2]. As
discussed in that mail thread, it's _not_ a bug in the JDK
implementation, since it still throws an IOException (which both
ConnectException and NoRouteToHostException are) from the
Socket.connect(...) call, as per its (javadoc) contract. That mail
thread has additional details on the exact case where this behaviour
difference is noticed and the reason for it.
With that context, should the implementation in the Apache HTTP client
be changed to take care of this inconsistency? Should both
ConnectException and NoRouteToHostException be treated the same in the
retry handling logic?
To make it easier to test/check this issue, I have a shared a reproducer
here[3] as a github repo which shows what's going on. It uses Apache
HTTP client 4.5.13 and as noted in the README.md, running that example
with Java 11 and Java 16 will show the inconsistency - the log messages
will show that the RetryExec will retry the request in Java 16, whereas
it won't in Java 11:
> RetryExec - Retrying request to {}->http://microprofile.io:1234
[1] https://github.com/quarkusio/quarkus/pull/19559#issue-717104474
[2] https://mail.openjdk.java.net/pipermail/net-dev/2021-August/016409.html
[3] https://github.com/jaikiran/httpclient-reproducer
-Jaikiran
---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscr...@hc.apache.org
For additional commands, e-mail: httpclient-users-h...@hc.apache.org