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

Java AsyncHttpClient可以执行非阻塞、异步HTTP调用吗?,java,netty,asynchttpclient,Java,Netty,Asynchttpclient,全部, 我正在尝试决定是否在我的应用程序中使用NodeJS或Java。我将通过HTTP与CouchDB通信,并希望采用异步非阻塞设计,在这种设计中,我的应用程序线程可以在等待CouchDB的查询响应时处理其他请求 我更喜欢使用Java,几天来我一直在研究AsyncHttpClient作为一种潜在的解决方案。然而,我在理解图书馆方面遇到了一些困难,我认为我可能对某些东西有一个根本性的误解 我在这里贴了一个要点: 我希望这个要点能够为每个请求打印出“请求X已发送!”和“响应X:something”。

全部,

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

我更喜欢使用Java,几天来我一直在研究AsyncHttpClient作为一种潜在的解决方案。然而,我在理解图书馆方面遇到了一些困难,我认为我可能对某些东西有一个根本性的误解

我在这里贴了一个要点:

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

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

我根本上误解了什么吗?在Java中可以做这种事情吗?AsyncHttpClient就是答案吗?这个问题是相关的,但不确定自2011年以来情况是否发生了变化()

由于NodeJS运行一个事件循环,这种非阻塞、异步行为是标准的。您只需注册一个回调函数来处理接收到的DB响应,同时事件循环只需处理其他事情

任何和所有的建议都将不胜感激

谢谢,
Conor

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

通常,Http异步请求使用请求提交->请求接受->作业轮询->作业响应来实现


Asyn请求是使用POST/PUT实现的,在这里,您提交一个请求,并在HTTP头中获得一个轮询URL以异步获得结果。现在您可以对此进行轮询以获得结果,如果结果可用,您应该得到200 OK,其中一些结果为xml/json/text输出,否则您可能会得到错误HTTP代码,例如503服务不可用。

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;
    }
  }
}
公共类MyAsyncHttpClientTest{
公共静态void main(字符串[]args)引发异常{
AsyncHttpClient AsyncHttpClient=新的AsyncHttpClient();
对于(int i=0;i<10;i++){
asyncHttpClient.prepareGet(“http://www.google.com")
.执行(新的CompletionHandler(i));
System.out.println(String.format(“请求%d已发送!”,i));
System.out.flush();
}
}
静态类CompletionHandler扩展了AsyncCompletionHandler{
私人最终要求编号;
public CompletionHandler(int-reqNumber){this.reqNumber=reqNumber;}
@重写未完成的公共Void(响应)引发异常{
System.out.println(String.format(“响应%d:%s”),reqNumber,
response.getResponseBody());
返回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>

...
已发送请求0!
请求1已发送!
请求2已发送!
请求3已发送!
请求4已发送!
请求5已发送!
请求6已发送!
请求7已发送!
请求8已发送!
请求9已发送!
答复1:
302移动
302移动
文档已移动
.
答复0:
302移动
302移动
文档已移动
.
...

唯一的问题是,由于没有关闭客户机的代码,因此该进程处于挂起状态,但这是另一回事。

是的。看一看vert.xnode.js作为一个轻量级的反向代理/网关是相当不错的,它带有couchdb的次要应用程序逻辑,这仅仅是因为Coach的http接口和node的简单异步http插件。java对于重应用程序逻辑更具性能。1)AsyncCompletionHandler文档表示,T值将由相关的Future返回,因此即使您没有看到Future,也会涉及到它。2)我认为您不会在这里演示非阻塞部分。您刚刚展示了它实际上是异步的。对于非阻塞,您需要表明触发请求的ahc线程并不总是与处理响应的ahc线程相同。非阻塞线程应该触发请求并返回池中的可用线程,而不是等待响应
。您需要表明触发请求的ahc线程并不总是与处理响应的ahc线程相同
——一个线程可以触发请求,阻塞原始响应,然后让另一个线程处理它,这样它将再次证明什么都没有。这里的最终证据是发出的请求比线程多,但这个答案并不是关于AHC中的不信任程度。至于对未来的评论,这更多的是吹毛求疵,显示的代码没有使用任何未来。