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

Reply via email to