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]