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] [Created] (HTTPASYNC-54) AsyncClient.execute hangs (or extremely slow) if Future.get is invoked between requests
Date Sun, 15 Sep 2013 04:10:54 GMT
Ben Christensen created HTTPASYNC-54:
----------------------------------------

             Summary: 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