I'm currently in a project where I have to do multiple, concurrent http requests to a rest service which returns a JSON response. This is a batch operation and the number of requests at any time could range from several hunderd to several thousend.
That's why I thought it would be a good idea to have an async http client so I could have concurrent requests, which dramatically could speed up the process. I first tried ning's async-http-client. Maybe I was doing something wrong, because it was kind of slow for me. About 10 seconds for 1000 requests.
After which I tried Apache's implementation which was much faster at about 4 seconds for 1000 requests. But I can't seem to get the requests to get stable. Most of the time I will get a List with a 1000 responses (like I expect), but sometimes I am just missing a few responses, like 1 or 2.
This is currently my code:
public class AsyncServiceTest {
public AsyncServiceTest(String serviceURI) {
this.httpClient = HttpAsyncClients.custom().setMaxConnPerRoute(100).setMaxConnTotal(20)
.setDefaultRequestConfig(RequestConfig.custom().build()).build();
this.objectMapper = new ObjectMapper();
this.serviceURI = serviceURI;
}
private List<Object> getResults(List<String> queryStrings) throws Exception {
try {
httpClient.start();
final List<HttpGet> requests = new ArrayList<>(addresses.size());
for (String str : queryStrings) {
requests.add(new HttpGet(buildUri(str))); // In this method we build the absolute request uri.
}
final CountDownLatch latch = new CountDownLatch(requests.size());
final List<Object> responses = new ArrayList<>(requests.size());
final List<String> stringResponses = new ArrayList<>(requests.size());
for (final HttpGet request : requests) {
httpClient.execute(request, new FutureCallback<HttpResponse>() {
@Override
public void completed(HttpResponse response) {
try {
stringResponses.add(IOUtils.toString(response.getEntity().getContent(), "UTF-8"));
latch.countDown();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void failed(Exception e) {
latch.countDown();
}
@Override
public void cancelled() {
latch.countDown();
}
});
}
latch.await();
for (String r : stringResponses) {
responses.add(mapToLocation(r)); // Mapping some Strings to JSON in this method.
}
return responses;
} finally {
httpClient.close();
}
}
}
So, in essence, I am wondering if there is something wrong with my code (probably) or is it just because of the way the library works? Because the CountDownLatch is at zero all the time. Or does anyone have a pointer in the right direction (maybe with another library)?