Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

can AsyncHttpClient perform non-blocking, async HTTP calls?

All,

I am trying to decide whether to use NodeJS or Java for my application. I will be communicating with CouchDB over HTTP and would like an asynchronous non-blocking design where my application thread can process additional requests while it waits on the query response from CouchDB.

I would prefer to use Java and I have been looking at AsyncHttpClient for a few days as a potential solution. However, I am having some trouble understanding the library and think I may have a fundamental misunderstanding of something.

I posted a gist here: https://gist.github.com/conorgil/5505603

I would expect this gist to print out "Request X sent!" AND "Response X: something" for each request. However, it appears that the HTTP call is not made (and thus, the handler not executed) until each Future calls get(). Uncommenting line 23 f.get() makes the code work as expected, but the call to Future#get() is blocking, correct? Is there a way to just provide a callback function that gets executed once the HTTP response is fully retrieved without blocking?

Something like the following: 1) request comes in on main thread 2) async, non-blocking HTTP call is made to CouchDB. A completion handler is registered to process the response from CouchDB 3) the main thread is now free to process the next request 4) HTTP response from CouchDB arrives at some point and the registered handler is called to perform some business logic 5) main thread continues just processing requests (for requests that do not need to hit CouchDB, they can be responded to very quickly)

Am I fundamentally misunderstanding something here? Is it possible to do this type of thing in Java? Is AsyncHttpClient the answer? This question is related, but not sure if things have changed since 2011 (Perform Async Connect with Java AsyncHttpClient Library?)

Since NodeJS runs an event loop, this non-blocking, async behavior is standard. You would just register a callback function to handle the DB response when it was received and the event loop would just process other things in the meantime.

Any and all advice is appreciated.

Thanks, Conor

like image 557
conorgil Avatar asked Oct 22 '22 10:10

conorgil


1 Answers

The main purpose of AsyncHttpClient is non-blocking HTTP and I have successfully used it to that effect. For example, I ran this simplified version of your code:

public class MyAsyncHttpClientTest {
  public static void main(String[] args) throws Exception {
    AsyncHttpClient asyncHttpClient = new AsyncHttpClient();
    for (int i = 0; i < 10; i++) {
      asyncHttpClient.prepareGet("http://www.google.com")
        .execute(new CompletionHandler(i));
      System.out.println(String.format("Request %d sent! ", i));
      System.out.flush();
    }
  }
  static class CompletionHandler extends AsyncCompletionHandler<Void> {
    private final int reqNumber;
    public CompletionHandler(int reqNumber) { this.reqNumber = reqNumber; }
    @Override public Void onCompleted(Response response) throws Exception {
      System.out.println(String.format("Response %d: %s", reqNumber,
          response.getResponseBody()));
      return null;
    }
  }
}

Notice no futures are involved. It produces the following output, just as one should expect:

Request 0 sent! 
Request 1 sent! 
Request 2 sent! 
Request 3 sent! 
Request 4 sent! 
Request 5 sent! 
Request 6 sent! 
Request 7 sent! 
Request 8 sent! 
Request 9 sent! 
Response 1: <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.hr/">here</A>.
</BODY></HTML>

Response 0: <HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.hr/">here</A>.
</BODY></HTML>

...

The only trouble is, the process is left hanging because there is no code that shuts down the client, but that's a separate story.

like image 50
Marko Topolnik Avatar answered Oct 30 '22 00:10

Marko Topolnik