hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Oleg Kalnichevski (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (HTTPCLIENT-1805) Blocking thread when executing a request in a FutureCallback
Date Mon, 23 Jan 2017 13:07:26 GMT

    [ https://issues.apache.org/jira/browse/HTTPCLIENT-1805?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15834444#comment-15834444
] 

Oleg Kalnichevski edited comment on HTTPCLIENT-1805 at 1/23/17 1:07 PM:
------------------------------------------------------------------------

bq. This is not the best solution because I think I will loose a lot of performance

What makes you think so? It might in fact improve performance under load by not blocking I/O
dispatch threads on the global lock of the connection pool.

bq.  Are there plans when the project is able to provide a version 5?

I am trying to get HttpClient ready for 5.0-alpha2 release by early March.

Oleg


was (Author: olegk):
bq. This is not the best solution because I think I will loose a lot of performance

What makes you think so? It might in fact improve performance under load by not blocking I/O
dispatch threads on the global lock of the connection pool.

bq.  Are there plans when the project is able to provide a version 5?

I am trying to get HttpClient ready for 5.0-alpha2 released by early March.

Oleg

> Blocking thread when executing a request in a FutureCallback
> ------------------------------------------------------------
>
>                 Key: HTTPCLIENT-1805
>                 URL: https://issues.apache.org/jira/browse/HTTPCLIENT-1805
>             Project: HttpComponents HttpClient
>          Issue Type: Improvement
>          Components: HttpClient (async)
>         Environment: Environment Oracle JDK 8u121
>            Reporter: Michael Ernst
>            Priority: Critical
>             Fix For: 5.0
>
>         Attachments: blocking-thread-example-application.zip
>
>
> When executing a request within a {{FutureCallback}} (inner request) the invoking thread
is blocked. The inner request will not be executed and processing the request terminates after
the write event.
> If the inner request is executed in another thread, the application works fine (see the
thenApplyAsync note in the code).
> This issue seems already be an issue for another user who reported this in a StackOverflow
question: http://stackoverflow.com/questions/32031846/apaches-httpasyncclient-never-returns-after-execute
> See the following log when it blocks:
> {noformat}
> IM-WEBAPP 2017-01-20 09:27:44,506 [I/O dispatcher 1] DEBUG org.apache.http.impl.nio.client.MainClientExec
 - [exchange: 4] start execution
> IM-WEBAPP 2017-01-20 09:27:44,507 [I/O dispatcher 1] DEBUG org.apache.http.client.protocol.RequestAddCookies
 - CookieSpec selected: default
> IM-WEBAPP 2017-01-20 09:27:44,507 [I/O dispatcher 1] DEBUG org.apache.http.client.protocol.RequestAuthCache
 - Auth cache not set in the context
> IM-WEBAPP 2017-01-20 09:27:44,507 [I/O dispatcher 1] DEBUG org.apache.http.impl.nio.client.InternalHttpAsyncClient
 - [exchange: 4] Request connection for {tls}->http://localhost:3128->https://permissions-api.apps.bosch-iot-cloud.com:443
> IM-WEBAPP 2017-01-20 09:27:44,507 [I/O dispatcher 1] DEBUG org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager
 - Connection request: [route: {tls}->http://localhost:3128->https://permissions-api.apps.bosch-iot-cloud.com:443][total
kept alive: 1; route allocated: 1 of 20; total allocated: 1 of 200]
> IM-WEBAPP 2017-01-20 09:27:44,507 [I/O dispatcher 1] DEBUG org.apache.http.impl.nio.conn.ManagedNHttpClientConnectionImpl
 - http-outgoing-0 127.0.0.1:57860<->127.0.0.1:3128[ACTIVE][r:r][ACTIVE][r][NOT_HANDSHAKING][0][0][0][0]:
Set timeout 0
> IM-WEBAPP 2017-01-20 09:27:44,507 [I/O dispatcher 1] DEBUG org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager
 - Connection leased: [id: http-outgoing-0][route: {tls}->http://localhost:3128->https://permissions-api.apps.bosch-iot-cloud.com:443][total
kept alive: 0; route allocated: 1 of 20; total allocated: 1 of 200]
> IM-WEBAPP 2017-01-20 09:27:44,507 [I/O dispatcher 1] DEBUG org.apache.http.impl.nio.client.InternalHttpAsyncClient
 - [exchange: 4] Connection allocated: CPoolProxy{http-outgoing-0 [ACTIVE]}
> IM-WEBAPP 2017-01-20 09:27:44,507 [I/O dispatcher 1] DEBUG org.apache.http.impl.nio.conn.ManagedNHttpClientConnectionImpl
 - http-outgoing-0 127.0.0.1:57860<->127.0.0.1:3128[ACTIVE][r:r][ACTIVE][r][NOT_HANDSHAKING][0][0][0][0]:
Set attribute http.nio.exchange-handler
> IM-WEBAPP 2017-01-20 09:27:44,508 [I/O dispatcher 1] DEBUG org.apache.http.impl.nio.conn.ManagedNHttpClientConnectionImpl
 - http-outgoing-0 127.0.0.1:57860<->127.0.0.1:3128[ACTIVE][rw:r][ACTIVE][rw][NOT_HANDSHAKING][0][0][0][0]:
Event set [w]
> {noformat}
> The stack of the blocking thread:
> {noformat}
> Thread [I/O dispatcher 1] (Suspended)	
> 	sun.misc.Unsafe.park(boolean, long) line: not available [native method]	
> 	java.util.concurrent.locks.LockSupport.park(java.lang.Object) line: 175	
> 	java.util.concurrent.CompletableFuture$Signaller.block() line: 1693	
> 	java.util.concurrent.ForkJoinPool.managedBlock(java.util.concurrent.ForkJoinPool$ManagedBlocker)
line: 3323	
> 	java.util.concurrent.CompletableFuture<T>.waitingGet(boolean) line: 1729	
> 	java.util.concurrent.CompletableFuture<T>.get() line: 1895	
> 	BlockingThreadMainApplication.lambda$0(org.apache.http.impl.nio.client.CloseableHttpAsyncClient,
java.io.InputStream) line: 60	
> 	BlockingThreadMainApplication$$Lambda$4.1112414583.apply(java.lang.Object) line: not
available	
> 	java.util.concurrent.CompletableFuture<T>.uniApply(java.util.concurrent.CompletableFuture<S>,
java.util.function.Function<? super S,? extends T>, java.util.concurrent.CompletableFuture.UniApply<S,T>)
line: 602	
> 	java.util.concurrent.CompletableFuture$UniApply<T,V>.tryFire(int) line: 577	
> 	java.util.concurrent.CompletableFuture<T>.postComplete() line: 474	
> 	java.util.concurrent.CompletableFuture<T>.complete(T) line: 1962	
> 	BlockingThreadMainApplication$1.completed(org.apache.http.HttpResponse) line: 83	
> 	BlockingThreadMainApplication$1.completed(java.lang.Object) line: 1	
> 	org.apache.http.concurrent.BasicFuture<T>.completed(T) line: 119	
> 	org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl<T>.responseCompleted()
line: 177	
> 	org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(org.apache.http.nio.NHttpClientConnection,
org.apache.http.nio.protocol.HttpAsyncRequestExecutor$State, org.apache.http.nio.protocol.HttpAsyncClientExchangeHandler)
line: 436	
> 	org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(org.apache.http.nio.NHttpClientConnection,
org.apache.http.nio.ContentDecoder) line: 326	
> 	org.apache.http.impl.nio.client.InternalRequestExecutor.inputReady(org.apache.http.nio.NHttpClientConnection,
org.apache.http.nio.ContentDecoder) line: 83	
> 	org.apache.http.impl.nio.conn.ManagedNHttpClientConnectionImpl(org.apache.http.impl.nio.DefaultNHttpClientConnection).consumeInput(org.apache.http.nio.NHttpClientEventHandler)
line: 265	
> 	org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(org.apache.http.impl.nio.DefaultNHttpClientConnection)
line: 81	
> 	org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(java.lang.Object) line:
39	
> 	org.apache.http.impl.nio.client.InternalIODispatch(org.apache.http.impl.nio.reactor.AbstractIODispatch<T>).inputReady(org.apache.http.nio.reactor.IOSession)
line: 121	
> 	org.apache.http.impl.nio.reactor.BaseIOReactor.readable(java.nio.channels.SelectionKey)
line: 162	
> 	org.apache.http.impl.nio.reactor.BaseIOReactor(org.apache.http.impl.nio.reactor.AbstractIOReactor).processEvent(java.nio.channels.SelectionKey)
line: 337	
> 	org.apache.http.impl.nio.reactor.BaseIOReactor(org.apache.http.impl.nio.reactor.AbstractIOReactor).processEvents(java.util.Set<java.nio.channels.SelectionKey>)
line: 315	
> 	org.apache.http.impl.nio.reactor.BaseIOReactor(org.apache.http.impl.nio.reactor.AbstractIOReactor).execute()
line: 276	
> 	org.apache.http.impl.nio.reactor.BaseIOReactor.execute(org.apache.http.nio.reactor.IOEventDispatch)
line: 104	
> 	org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run() line: 588

> 	java.lang.Thread.run() line: 745	
> {noformat}
> Be aware that this issue could sometimes be a Heisenbug and the application terminates
successfully in debugging. When running normally it fails on my machine with 100%.
> You can simply reproduce this issue with the following code or use the attached maven
project:
> {code:java}
> import java.io.IOException;
> import java.io.InputStream;
> import java.util.concurrent.CompletableFuture;
> import java.util.concurrent.ExecutionException;
> import org.apache.http.HttpHost;
> import org.apache.http.HttpResponse;
> import org.apache.http.client.config.RequestConfig;
> import org.apache.http.client.methods.HttpGet;
> import org.apache.http.concurrent.FutureCallback;
> import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
> import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
> import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
> import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
> import org.apache.http.nio.reactor.IOReactorException;
> public class BlockingThreadMainApplication
> {
>    private static final int POOL_PER_ROUTE = 20;
>    private static final int POOL_MAX = 200;
>    private static final int CONNECT_TIMEOUT = 10000;
>    private static final int SOCKET_TIMEOUT = 60000;
>    private static final String PUBLIC_KEYS_URL = "https://permissions-api.apps.bosch-iot-cloud.com/2/rest/publickeys";
>    private static HttpHost proxy = null;
>    private int requestCounter = 0;
>    public static void main(final String[] args) throws InterruptedException, ExecutionException,
IOException
>    {
>       // include this lines if you are behind a proxy server
>       // proxy = new HttpHost("localhost", 3128);
>       final BlockingThreadMainApplication application = new BlockingThreadMainApplication();
>       try (CloseableHttpAsyncClient asyncClient = application.createAsynClient())
>       {
>          // these request work like they should
>          application.createRequest(asyncClient).get();
>          application.createRequest(asyncClient).get();
>          System.out.println("Execute request with inner request");
>          final Object object = application.createRequestWithInnerRequest(asyncClient).get();
>          // will never be invoked
>          System.out.println("Yeaha, application completed. Resolved last response " +
object.getClass().getName());
>       }
>    }
>    private CompletableFuture<?> createRequestWithInnerRequest(final CloseableHttpAsyncClient
asyncClient)
>       throws InterruptedException, ExecutionException
>    {
>       // it works like a charm when using thenApplyAsync so it is executed in another
thread
>       return createRequest(asyncClient).thenApply(i ->
>       {
>          // execute another request and get its result
>          try
>          {
>             System.out.println("executing request in thenApply");
>             createRequest(asyncClient).get(); // never comes back
>             System.out.println("executed request in thenApply");
>          }
>          catch (InterruptedException | ExecutionException e)
>          {
>             throw new IllegalStateException(e);
>          }
>          return i;
>       });
>    }
>    public CompletableFuture<InputStream> createRequest(final CloseableHttpAsyncClient
asyncClient)
>    {
>       final int requestId = ++requestCounter;
>       final CompletableFuture<InputStream> toBeCompleted = new CompletableFuture<>();
>       final FutureCallback<HttpResponse> callback = new FutureCallback<HttpResponse>()
>       {
>          @Override
>          public void completed(final HttpResponse response)
>          {
>             System.out.println("completed " + requestId);
>             try
>             {
>                toBeCompleted.complete(response.getEntity().getContent());
>             }
>             catch (UnsupportedOperationException | IOException e)
>             {
>                System.out.println("failed to get InputStream from response " + requestId);
>                toBeCompleted.completeExceptionally(e);
>             }
>          }
>          @Override
>          public void cancelled()
>          {
>             System.out.println("cancelled " + requestId);
>             toBeCompleted.cancel(true);
>          }
>          @Override
>          public void failed(final Exception e)
>          {
>             System.out.println("failed " + requestId);
>             toBeCompleted.completeExceptionally(e);
>          }
>       };
>       asyncClient.execute(getGetRequest(), callback);
>       return toBeCompleted;
>    }
>    private CloseableHttpAsyncClient createAsynClient()
>    {
>       // Create common default configuration
>       final RequestConfig clientConfig = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT)
>          .setSocketTimeout(SOCKET_TIMEOUT).setConnectionRequestTimeout(SOCKET_TIMEOUT).setProxy(proxy).build();
>       DefaultConnectingIOReactor ioreactor;
>       PoolingNHttpClientConnectionManager asyncConnectionManager;
>       try
>       {
>          ioreactor = new DefaultConnectingIOReactor();
>          asyncConnectionManager = new PoolingNHttpClientConnectionManager(ioreactor);
>          asyncConnectionManager.setMaxTotal(POOL_MAX);
>          asyncConnectionManager.setDefaultMaxPerRoute(POOL_PER_ROUTE);
>       }
>       catch (final IOReactorException e)
>       {
>          throw new RuntimeException(e);
>       }
>       final CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create().setDefaultRequestConfig(clientConfig)
>          .setConnectionManager(asyncConnectionManager).build();
>       client.start();
>       return client;
>    }
>    private HttpGet getGetRequest()
>    {
>       return new HttpGet(PUBLIC_KEYS_URL);
>    }
> }
> {code}
> I don't think it is related to HTTPASYNC-35 or HTTPASYNC-34 who sounds similiar.
> Just one last note: Why is 4.1.2 released but not in this Jira project?



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@hc.apache.org
For additional commands, e-mail: dev-help@hc.apache.org


Mime
View raw message