[
https://issues.apache.org/jira/browse/HTTPCLIENT-2386?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18032369#comment-18032369
]
Jens Popp commented on HTTPCLIENT-2386:
---------------------------------------
This issue caused a change in behavior in a minor build that was difficult to
detect. Basically I have connectTimout and requestTimeout. I want to have a
fast fail if the connection including tls handshake cannot be established, but
the request can take very long. In 5.5 this worked with some settings as
described below. The commit and 5.5.1 cause a change in behavior that the tls
handshake failure is no longer covered and the request timeout is used in 5.5.1
Old code worked in 5.5:
{code:java}
final TlsSocketStrategy tlsSocketStrategey = sslContext != null
? new DefaultClientTlsStrategy(sslContext, verifier)
: null;
final PoolingHttpClientConnectionManagerBuilder
connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder
.create().setPoolConcurrencyPolicy(PoolConcurrencyPolicy.STRICT)
.setConnPoolPolicy(PoolReusePolicy.LIFO).setTlsSocketStrategy(tlsSocketStrategey);
final ConnectionConfig.Builder connConfig =
ConnectionConfig.custom();
if (connectTimeout != null) {
connectionManagerBuilder
.setDefaultConnectionConfig(
ConnectionConfig.custom().setConnectTimeout(Timeout.of(connectTimeout))
.setSocketTimeout(Timeout.of(connectTimeout)).build())
.setDefaultSocketConfig(SocketConfig.custom().setSoTimeout(Timeout.of(connectTimeout)).build())
.build();
}
// Request Timeout is set in interceptor
connectionManagerBuilder.setDefaultConnectionConfig(connConfig.build());
final HttpClientBuilder builder = HttpClients.custom()
.setConnectionManager(connectionManagerBuilder.build());
... {code}
New code required from 5.5.1
{code:java}
final TlsSocketStrategy tlsSocketStrategey = sslContext != null
? new DefaultClientTlsStrategy(sslContext, verifier)
: null;
// New fix due to changes in 5.5.1 ;
TlsConfig tlsConfig = sslContext != null
?
TlsConfig.custom().setHandshakeTimeout(Timeout.of(connectTimeout)) // TLS
handshake specific
.build()
: null;
final PoolingHttpClientConnectionManagerBuilder
connectionManagerBuilder = PoolingHttpClientConnectionManagerBuilder
.create().setPoolConcurrencyPolicy(PoolConcurrencyPolicy.STRICT)
.setConnPoolPolicy(PoolReusePolicy.LIFO).setTlsSocketStrategy(tlsSocketStrategey)
.setDefaultTlsConfig(tlsConfig);
... same as above{code}
> httpClient5 socketTimeoutException in dataChannel with connectTimeout value
> ---------------------------------------------------------------------------
>
> Key: HTTPCLIENT-2386
> URL: https://issues.apache.org/jira/browse/HTTPCLIENT-2386
> Project: HttpComponents HttpClient
> Issue Type: Improvement
> Components: HttpClient (async)
> Affects Versions: 5.4.4
> Environment: httpclient5 version: 5.4.4
> httpCore5 version: 5.3.4
> Java version: 17 (21 since recently)
> Reporter: Cenk Pekyaman
> Priority: Minor
> Fix For: 5.5.1, 5.6-alpha1
>
> Time Spent: 5h
> Remaining Estimate: 0h
>
> We are using http-client-5 under our api-client layer with async + TLS. Once
> in a while, we get a timeout exception like this:
> "{*}java.net.SocketTimeoutException: 2 SECONDS{*}" in some requests. and from
> the stack trace, we see that the exception is coming from
> "InternalDataChannel.onTimeout". but the value we see is actually the
> {*}connectTimeout{*}, not the readTimeout({*}socketTimeout{*}) we set for the
> request.
> we specify our *connectTimeout* as *2 seconds* in
> *PoolingAsyncClientConnectionManagerBuilder* during client creation. we
> specify our *socketTimeout* as *10 seconds* in *RequestConfig* of
> *HttpClientContext* during request execution.
>
> this is how we make the call (a bit simplified):
> {{// the last parameter is our class implementing FutureCallback}}
> {{Future<Message<HttpResponse, RES>> clientFuture =
> asyncHttpClient.execute(asyncRequestProducer, responseConsumer, null,
> httpClientContext, this);}}
> {{// callTimeout is essentially connectTimeout + socketTimeout by default.}}
> {{return clientFuture.get(callTimeout, TimeUnit.MILLISECONDS);}}
>
> We suspect that the client completes the initial connect step with
> "InternalConnectChannel" and then the socket is handed over to
> "InternalDataChannel" to do the TLS handshake in "{*}startTls{*}", which
> either takes too long to complete, or hangs. Since we don't specify
> handshakeTimeout in our tlsconfig, *DefaultAsyncClientConnectionOperator*
> seems to be using *connectTimeout* for this stage (in the callback called
> after connection is established ?).
>
> Code flow is essentially correct but getting a generic socketTimeoutException
> with the value of connectTimeout seems a bit confusing, as we normally expect
> some ConnectTimeoutException if we really have a connection timeout, or the
> other way around.
>
> This is an example stack trace for such a case:
> {{ at org.apache.hc.core5.concurrent.BasicFuture.failed(BasicFuture.java:166)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.concurrent.ComplexFuture.failed(ComplexFuture.java:79)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.client5.http.impl.async.InternalAbstractHttpAsyncClient$2.failed(InternalAbstractHttpAsyncClient.java:364)
> [httpclient5-5.4.4.jar:5.4.4] at
> org.apache.hc.client5.http.impl.async.AsyncRedirectExec$1.failed(AsyncRedirectExec.java:246)
> [httpclient5-5.4.4.jar:5.4.4] at
> org.apache.hc.client5.http.impl.async.AsyncProtocolExec$1.failed(AsyncProtocolExec.java:295)
> [httpclient5-5.4.4.jar:5.4.4] at
> org.apache.hc.client5.http.impl.async.AsyncConnectExec$2.failed(AsyncConnectExec.java:233)
> [httpclient5-5.4.4.jar:5.4.4] at
> org.apache.hc.core5.concurrent.CallbackContribution.failed(CallbackContribution.java:52)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.concurrent.BasicFuture.failed(BasicFuture.java:166)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.concurrent.ComplexFuture.failed(ComplexFuture.java:79)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager$4.failed(PoolingAsyncClientConnectionManager.java:482)
> [httpclient5-5.4.4.jar:5.4.4] at
> org.apache.hc.core5.concurrent.BasicFuture.failed(BasicFuture.java:166)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.concurrent.ComplexFuture.failed(ComplexFuture.java:79)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.concurrent.FutureContribution.failed(FutureContribution.java:52)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.concurrent.CallbackContribution.failed(CallbackContribution.java:52)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.reactor.ssl.SSLIOSession$1.exception(SSLIOSession.java:233)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.reactor.ssl.SSLIOSession$1.timeout(SSLIOSession.java:223)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.reactor.InternalDataChannel.onTimeout(InternalDataChannel.java:170)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.reactor.InternalChannel.checkTimeout(InternalChannel.java:67)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.reactor.SingleCoreIOReactor.checkTimeout(SingleCoreIOReactor.java:239)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.reactor.SingleCoreIOReactor.validateActiveChannels(SingleCoreIOReactor.java:166)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:128)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:92)
> [httpcore5-5.3.4.jar:5.3.4] at
> org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44)
> [httpcore5-5.3.4.jar:5.3.4] at java.lang.Thread.run(Thread.java:840) [?:?]
> Caused by: java.net.SocketTimeoutException: 2 SECONDS at
> org.apache.hc.core5.io.SocketTimeoutExceptionFactory.create(SocketTimeoutExceptionFactory.java:50)
> ~[httpcore5-5.3.4.jar:5.3.4]}}
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]