AsyncHttpClient可以执行非阻塞,异步HTTP调用吗?

时间:2013-05-03 00:25:04

标签: java netty asynchttpclient

所有

我正在尝试决定是否将NodeJS或Java用于我的应用程序。我将通过HTTP与CouchDB进行通信,并希望采用异步非阻塞设计,我的应用程序线程可以在等待来自CouchDB的查询响应时处理其他请求。

我更喜欢使用Java,我一直在寻找AsyncHttpClient作为潜在的解决方案。但是,我在理解图书馆方面遇到了一些麻烦,并认为我可能会对某些内容产生根本性的误解。

我在这里发表了一个要点:https://gist.github.com/conorgil/5505603

我希望这个要点打印出“请求X发送!”并为每个请求“响应X:某事”。但是,在每个Future调用get()之前,似乎没有进行HTTP调用(因此,处理程序没有执行)。取消注释第23行f.get()会使代码按预期工作,但对Future#get()的调用是阻塞的,对吗?有没有办法只提供一个回调函数,一旦HTTP响应被完全检索而没有阻塞就会被执行?

如下所示: 1)请求进入主线程 2)对CouchDB进行异步,非阻塞HTTP调用。注册完成处理程序以处理来自CouchDB的响应 3)主线程现在可以自由处理下一个请求 4)来自CouchDB的HTTP响应到达某个点,并且调用注册的处理程序来执行某些业务逻辑 5)主线程继续处理请求(对于不需要命中CouchDB的请求,可以非常快速地响应)

我从根本上误解了一些事情吗?是否可以在Java中执行此类操作?是AsyncHttpClient的答案吗?这个问题是相关的,但不确定自2011年以来情况是否发生了变化(Perform Async Connect with Java AsyncHttpClient Library?

由于NodeJS运行事件循环,因此这种非阻塞的异步行为是标准的。您只需注册一个回调函数来处理收到它时的数据库响应,并且事件循环在此期间只处理其他事情。

赞赏任何建议。

谢谢, 康纳

2 个答案:

答案 0 :(得分:2)

AsyncHttpClient的主要目的是非阻塞HTTP,我已成功地将其用于此效果。例如,我运行了代码的简化版本:

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;
    }
  }
}

请注意,不涉及期货。它产生以下输出,就像人们期望的那样:

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>

...

唯一的麻烦是,由于没有关闭客户端的代码,因此流程处于暂停状态,但这是一个单独的故事。

答案 1 :(得分:0)

如果您可以增强您的数据库http服务器以支持异步请求,那么我建议您这样做。

通常,使用REQUEST SUBMIT-&gt; REQUEST ACCEPTED-&gt;实现Http异步请求。工作轮询 - &gt;工作回应。

使用POST / PUT实现Asyn请求,您可以在其中提交请求,并在HTTP标头中获得202 Accepted以及轮询URL以异步获取结果。现在你可以轮询这个来获得结果,如果结果可用,你应该得到200 OK,一些结果为xml / json / text输出,否则你可能会得到错误的HTTP代码,例如503 Service Unavailable。