11

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

2
  • Just convert the first example from the apache async client to use HttpPost instead of HttpGet. Commented Jan 8, 2014 at 14:40
  • How about posting an answer with a working example and earn some credit? Commented Jan 8, 2014 at 15:10

2 Answers 2

4

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

Sign up to request clarification or add additional context in comments.

1 Comment

If you are using an extra IO Thread you are still harming the overall thread pool right ? at the end of the day you are using 1 thread more to handle the call back, isn't ?
-2

You could use the Java Executor framework:

First, create a Callable to do your work:

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:

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
}

4 Comments

Nice, but I rather use a library that does this for me, unless there isn't any, but as far as I see there are a few.
doesn't this simply fire a thread per request instead of true non-blocking i/o?
This is no different then blocking on the calling thread. You should use a NIO client to do proper non blocking requests.
This is nowhere related to what OP has asked. @forhas HttpClient is multithreaded so it could fit your use case. However I think what you are looking is a higher throughput client, so using a NIO based non blocking client makes sense. You should clarify this in your question. Also keep in mind that NIO clients will only help if you need to handle more concurrent connections, otherwise, the regular BIO client should be good.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.