arturobernalg opened a new pull request, #936: URL: https://github.com/apache/httpcomponents-client/pull/936
Implements RFC 8305 (Happy Eyeballs v2) connection racing for the Classic (blocking) client, as the third and final PR of this series, alongside apache/httpcomponents-client#935 (Async connection racing) and arturobernalg/httpcomponents-client#20 (Async independent A/AAAA resolution, stacked on #935 pending its merge). This PR is independent of the other two: the Classic client has its own connection path (java.net.Socket, not the reactor), so it needed its own, smaller mechanism rather than reusing the Async internals. ## Change DefaultHttpClientConnectionOperator (the Classic client's connection operator) can now race connection attempts across a host's resolved addresses instead of trying them strictly sequentially on the calling thread: - The first address is tried immediately, on a dedicated worker thread; each subsequent address is tried on its own worker thread after a configurable attempt delay (default 250ms, per RFC 8305 Section 8) unless an earlier attempt has already failed, in which case the next address is tried without further delay. - - The first attempt to connect successfully wins the race. Every other attempt's socket is closed: for an attempt still blocked in Socket#connect, closing its socket aborts that blocked call (the same mechanism java.net.Socket itself provides for cancelling a connect from another thread), so nothing is leaked; an attempt that has not yet started is prevented from ever creating a socket. - - The public, blocking connect() API is unchanged: the calling thread still blocks until a connection is obtained or every address has failed. The worker pool used for racing is created per call, bounded to the number of resolved addresses, and shut down before the call returns, so this adds no long-lived threads. - - TLS/ALPN negotiation happens only once, after a winning socket has been chosen, exactly as before this change; this PR does not touch it, or HTTP semantics, proxying, SOCKS, or local address binding, all of which are handled per attempt exactly as the existing single-attempt code already did. The feature is opt-in and defaults to disabled. When disabled (the default everywhere), the previous sequential, single-threaded behavior is preserved verbatim. Enabled via a new constructor overload on DefaultHttpClientConnectionOperator and new PoolingHttpClientConnectionManagerBuilder#setHappyEyeballsEnabled / #setConnectionAttemptDelay builder methods, mirroring the Async client's equivalents from #935. ## Tests New unit tests in HappyEyeballsSocketConnectorTest covering: a single address connecting without any racing overhead, a second address winning while the first is still genuinely blocked inside a (simulated) blocking connect call, with the loser's socket verified closed; all addresses failing with an aggregated IOException; a fast failure on the first address letting the second win without waiting out the stagger delay. The "still connecting" scenario uses a small Socket subclass whose connect() blocks until closed, matching the real behavior relied on to cancel an in-flight blocking connect. Ran: mvnw -pl httpclient5 -am test (full module) - all tests pass. ## Dependency None. Based directly on upstream master, independent of #935 and arturobernalg/httpcomponents-client#20. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
