java非阻塞HTTP客户端

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20998631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 05:50:14  来源:igfitidea点击:

java Non-blocking HTTP client

javaasynchronoushttp-postnonblocking

提问by forhas

I have a high volume java application in which I have to send http posts to another server. Currently I'm using org.apache.commons.httpclientlibrary:

我有一个高容量的 Java 应用程序,我必须在其中将 http 帖子发送到另一台服务器。目前我正在使用org.apache.commons.httpclient库:

private static void sendData(String data) {
HttpClient httpclient = new HttpClient();
StringRequestEntity requestEntity;
try {
    requestEntity = new StringRequestEntity(data, "application/json", "UTF-8");
    String address = "http://<my host>/events/"
    PostMethod postMethod = new PostMethod(address);
    postMethod.setRequestEntity(requestEntity);

    httpclient.executeMethod(postMethod);

} catch (Exception e) {
    LOG.error("Failed to send data ", e);

}
}

This means I'm sending my http requests synchronously, which doesn't fit my multithreaded high volume app. So I would like to change those calls to asynchronous non-blocking http calls.

这意味着我正在同步发送我的 http 请求,这不适合我的多线程高容量应用程序。所以我想将这些调用更改为异步非阻塞 http 调用。

I was going through number of options such as apache async clientand xsocketbut was not able to make it work.

我正在经历许多选项,例如apache 异步客户端xsocket,但无法使其工作。

Tried ning:

尝试

private static void sendEventToGrpahiteAsync(String event) {
LOG.info("\n" + "sendEventToGrpahiteAsync");
try (AsyncHttpClient asyncHttpClient = new AsyncHttpClient()) {
    BoundRequestBuilder post = asyncHttpClient.preparePost();
    post.addHeader("Content-Type", "application/json");
    post.setBodyEncoding("UTF-8");
    post.setBody(event);
    post.execute(new HttpRequestCompletionHandler());
} catch (Exception e) {
    LOG.error("Failed to sending event", e);
}
}

I tried Apache HttpAsyncClient:

我试过 Apache HttpAsyncClient

private static void sendEventToGrpahiteAsync(String event) {
LOG.info("\n" + "sendEventToGrpahiteAsync");
try (CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault()) {
    httpclient.start();
    HttpPost request = new HttpPost(addr);
    StringEntity entity = new StringEntity(event, ContentType.create("application/json", Consts.UTF_8));
    request.setEntity(entity);
    httpclient.execute(request, null);
} catch (Exception e) {
    LOG.error("Failed to sending event", e);
}
}

I tried xsocket:

我试过xsocket

private static void sendEventToGrpahiteAsync2(String event) {
LOG.info("\n" + "sendEventToGrpahiteAsync");
try (INonBlockingConnection con = new NonBlockingConnection(<SERVER_IP>, 80);
    IHttpClientEndpoint httpClientConnection = new HttpClientConnection(con)) {
    IHttpResponseHandler responseHandler = new MyResponseHandler();
    IHttpRequest request = new PostRequest(url_address, "application/json", Consts.UTF_8.toString(), event);
    request.setTransferEncoding(Consts.UTF_8.toString());
    httpClientConnection.send(request, responseHandler);
} catch (Exception e) {
    LOG.error("Failed to sending event", e);
}
}

I get no exceptions but the post doesn't get to the target as well. To be clear, the target is a graphite serverso once a post arrives it is clearly seen in a graph. The synchronous posts works well, I can see the result on the graph, but none of the asynchronous posts shows on my destination graph.

我没有例外,但帖子也没有达到目标。需要明确的是,目标是一个石墨服务器,因此一旦帖子到达,它就可以在图表中清楚地看到。同步帖子运行良好,我可以在图表上看到结果,但没有任何异步帖子显示在我的目标图表上。

What am I missing?

我错过了什么?

Thanks

谢谢

采纳答案by forhas

Got it.

知道了。

All the libraries I'n using are implemented using an extra IO thread, so my process probably ends before a full handshake.

我使用的所有库都是使用额外的 IO 线程实现的,因此我的进程可能会在完全握手之前结束。

Once I added Thread.sleep(2000) after the http calls things worked just fine. So for a web app (which is my case) my suggested implementations are just fine (but for a java process you might consider NickJ's answer).

一旦我在 http 调用之后添加了 Thread.sleep(2000) 事情就很好了。因此,对于网络应用程序(这是我的情况),我建议的实现很好(但对于 Java 进程,您可能会考虑 NickJ 的答案)。

回答by NickJ

You could use the Java Executor framework:

您可以使用 Java Executor 框架:

First, create a Callable to do your work:

首先,创建一个 Callable 来完成你的工作:

public class MyCallable implements Callable<MyResult> {
  @Override
  public MyResult call() throws Exception {
    //do stuff
    return result;
  }
} 

Get an Exectutor which will run your Callable. There are various way to get one, here's one example:

获取将运行您的 Callable 的 Executor。有多种获取方式,以下是一个示例:

ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);

Finally, run it:

最后,运行它:

MyCallable callable = new MyCallable();
Future<MyResult> futureResult = executor.submit(callable);

Getting the result:

得到结果:

boolean resultReady = futureResult.isDone(); //is the result ready yet?
Result r = futureResult.get(); //wait for result and return it

try {
  Result r = futureResult.get(10, TimeUnit.SECONDS); //wait max. 10 seconds for result
} catch (TimeOutException e) {
  //result still not ready after waiting 10 seconds
}