hc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Ben Christensen (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (HTTPASYNC-54) AsyncClient.execute hangs (or extremely slow) if Future.get is invoked between requests
Date Mon, 16 Sep 2013 02:45:51 GMT

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

Ben Christensen commented on HTTPASYNC-54:
------------------------------------------

Thank you Oleg for your response and sample code. That code also failed for me so I spent
more time debugging and found the issue as JDK version 1.7.0_05 which I was accidentally using
instead of newer versions.

My execution environment was pointing to an old JDK version. Updating the runtime to a new
version made it work.

I posted my code and tests here: https://github.com/benjchristensen/HttpClientTest

The JDK 1.7.0_05 version becomes very slow or hangs, all other JVM versions I tested worked
fine.

So, it seems I did find some kind of odd issue, but thankfully it's against a single old JDK
version.

I apologize for not having caught this old environmental config before filing this issue.


                
> AsyncClient.execute hangs (or extremely slow) if Future.get is invoked between requests
> ---------------------------------------------------------------------------------------
>
>                 Key: HTTPASYNC-54
>                 URL: https://issues.apache.org/jira/browse/HTTPASYNC-54
>             Project: HttpComponents HttpAsyncClient
>          Issue Type: Bug
>    Affects Versions: 4.0-beta4
>         Environment: $ java -version
> java version "1.7.0_40"
> Java(TM) SE Runtime Environment (build 1.7.0_40-b43)
> Java HotSpot(TM) 64-Bit Server VM (build 24.0-b56, mixed mode)
> $ uname -a
> Darwin lgmac-bchristensen 12.5.0 Darwin Kernel Version 12.5.0: Mon Jul 29 16:33:49 PDT
2013; root:xnu-2050.48.11~1/RELEASE_X86_64 x86_64
>            Reporter: Ben Christensen
>
> When executing requests in a loop, if the returned Future<HttpResponse> is dereferenced
by calling get() it is expected it will cause the loop to happen sequentially, each request
happening one at a time.
> Pseudo code (this approach does not work):
>      for 1...5
>           Future f = asyncHttpClient.execute()
>           f.get()
> 	
> What actually happens is it seems to hang, or at best start taking several minutes per
requests as opposed to milliseconds.
> If the for-loop of requests is done completely asynchronously and the Futures just collected
and dereferenced after all requests are executed, then it works fine.
> Pseudo code (this approach works):
>      for 1...5
>           listOfFutures << asyncHttpClient.execute()
>      for f in listOfFutures
>           f.get()
> I intend on a completely non-blocking strategy, but there are times when blocking is
needed, and many will use my library in that manner, so I need this to work.
> Either I'm doing something very wrong, or there is indeed an issue. No amount of breakpoints
or debugging has led me yet to where the issue is, so sorry that all I can do is provide an
example of the problem and not a pointer to what I think the solution is.
> Thank you in advance for your time on this matter.
> Following is code that demonstrates the issue and log output of the scenarios:
> ----------------------------------------------------------
> Code demonstrating issue:
> ----------------------------------------------------------
> import java.util.concurrent.Future;
> import org.apache.http.HttpResponse;
> 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.HttpAsyncClients;
> import org.apache.http.protocol.BasicHttpContext;
> public class TestAynscHttpClient {
>     public static void main(String args[]) {
>         CloseableHttpAsyncClient client = HttpAsyncClients.createDefault();
>         client.start();
>         try {
>             /*
>              * This should execute 5 requests asynchronously and receive responses in
the FutureCallback handler.
>              * 
>              * If the `f.get()` line is invoked, only the first will work, no further
requests will execute
>              * (or sometimes if I leave it sitting for minutes I see a second request
go through).
>              * 
>              * If the `f.get()` line is commented out, then all 5 correctly execute and
return.
>              * 
>              * It is expected that if someone calls `f.get()` in this loop it should
cause the requests
>              * to happen sequentially, but they should still work.
>              */
>             for (int i = 0; i < 5; i++) {
>                 System.out.println("execute request");
>                 Future<HttpResponse> f = client.execute(new HttpGet("http://www.google.com"),
>                         new BasicHttpContext(), new FutureCallback<HttpResponse>()
{
>                             @Override
>                             public void failed(Exception ex) {
>                                 System.out.println("failed");
>                             }
>                             @Override
>                             public void completed(HttpResponse result) {
>                                 System.out.println("Result: " + result);
>                             }
>                             @Override
>                             public void cancelled() {
>                                 System.out.println("cancelled");
>                             }
>                         });
>                 try {
>                     f.get();// commenting out this line makes the 5 requests succeed
>                 } catch (Exception e) {
>                     e.printStackTrace();
>                 }
>                 System.out.println("after f.get()");
>             }
>             // wait for all async tasks to complete (when f.get is commented out)
>         } finally {
>             try {
>                 Thread.sleep(2000);
>                 client.close();
>             } catch (Exception e) {
>                 e.printStackTrace();
>             }
>         }
>     }
> }
> ----------------------------------------------------------
> Here is output with f.get() disabled:
> ----------------------------------------------------------
> 		
> execute request
> after f.get()
> execute request
> after f.get()
> execute request
> after f.get()
> execute request
> after f.get()
> execute request
> after f.get()
> Result: HTTP/1.1 200 OK [Date: Sun, 15 Sep 2013 03:45:00 GMT, Expire... cropped for brevity
> Result: HTTP/1.1 200 OK [Date: Sun, 15 Sep 2013 03:45:00 GMT, Expire... cropped for brevity
> Result: HTTP/1.1 200 OK [Date: Sun, 15 Sep 2013 03:45:00 GMT, Expire... cropped for brevity
> Result: HTTP/1.1 200 OK [Date: Sun, 15 Sep 2013 03:45:00 GMT, Expire... cropped for brevity
> Result: HTTP/1.1 200 OK [Date: Sun, 15 Sep 2013 03:45:00 GMT, Expire... cropped for brevity
> 		
> ----------------------------------------------------------
> Here is output with f.get() enabled:
> ----------------------------------------------------------
> execute request
> after f.get()
> execute request
> Result: HTTP/1.1 200 OK [Date: Sun, 15 Sep 2013 03:43:47 GMT, Expire... cropped for brevity
> ----------------------------------------------------------
> Here is output with f.get() enabled and letting it run
> for several minutes. Note several minutes between responses.
> ----------------------------------------------------------
> 		
> execute request
> after f.get()
> execute request
> Result: HTTP/1.1 200 OK [Date: Sun, 15 Sep 2013 03:38:59 GMT, Expire... cropped for brevity
> after f.get()
> execute request
> Result: HTTP/1.1 200 OK [Date: Sun, 15 Sep 2013 03:42:59 GMT, Expire... cropped for brevity
> ----------------------------------------------------------
> This code also hangs on the second request:
> ----------------------------------------------------------
>         try {
>             client.execute(new HttpGet("http://www.google.com"),
>                     new BasicHttpContext(), new FutureCallback<HttpResponse>()
{
>                         @Override
>                         public void failed(Exception ex) {
>                             System.out.println("failed");
>                         }
>                         @Override
>                         public void completed(HttpResponse result) {
>                             System.out.println("Result: " + result);
>                         }
>                         @Override
>                         public void cancelled() {
>                             System.out.println("cancelled");
>                         }
>                     }).get();
>             
>             client.execute(new HttpGet("http://www.apple.com"),
>                     new BasicHttpContext(), new FutureCallback<HttpResponse>()
{
>                         @Override
>                         public void failed(Exception ex) {
>                             System.out.println("failed");
>                         }
>                         @Override
>                         public void completed(HttpResponse result) {
>                             System.out.println("Result: " + result);
>                         }
>                         @Override
>                         public void cancelled() {
>                             System.out.println("cancelled");
>                         }
>                     }).get();
>         } catch (Exception e1) {
>             e1.printStackTrace();
>         }

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

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


Mime
View raw message