Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java Non-blocking HTTP client

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.httpclient library:

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.

I was going through number of options such as apache async client and xsocket but was not able to make it work.

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:

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:

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 server so 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

like image 441
forhas Avatar asked Jan 08 '14 14:01

forhas


1 Answers

Got it.

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

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).

like image 77
forhas Avatar answered Nov 14 '22 14:11

forhas