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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to