Question

I'm testing a Web application written in Java EE using servlets (version 7). I'm sending a lot of HTTP requests to my servlets and I want to know when all requests are completed.

To send requests I'm using an executor. Also I don't know if it is the most efficient way to do this.

 for (int i=0; i < numRequests; i++) {
     ExecutorService executor = Executors.newFixedThreadPool(1); 
     Future<util.Response> responseFromServlet = null;
        responseFromServlet = executor.submit(new util.Request(new URL(url)));
     if ( i !=  numRequests -1 ) {
        executor.shutdown();
     } else {
        responseFromServlet.get().getBody(); // suspensive call for last invocation
        executor.shutdown();
     }
  }

Actually the executor waits the end of the last invoked HTTP request but it usually is not the last one that completes.

I think that creating a new thread waiting for response of each HTTP servlet is crazy. I can't generate 100-200-300 threads, one for each request!

So is there a way to understand when all servlets end their execution? If needed, I can modify my servlets.

=== Edit ===

To be more precise, here is the Request class implementation:

public class Request implements Callable<Response> {
  private URL url;

  public Request(URL url) {
      this.url = url;
  }

  @Override
  public Response call() throws Exception {
      return new Response(url.openStream());
  }
}

And this it the Response class:

public class Response {
  private InputStream body;

  public Response(InputStream body) {
      this.body = body;
  }

  public InputStream getBody() {
      return body;
  }
}
Était-ce utile?

La solution

Using an executor is fine, you may want to increase the size of the ThreadPool though to have more concurrent threads performing your requests.

Use a CoutnDownLatch initialised with numRequests which sits waiting for all the threads to complete.

util.Request must call latch.countDown() in its runmethod

The code would look like this (handwritten - not tested)

ExecutorService executor = Executors.newFixedThreadPool(n);
final CountDownLatch latch = new CountDownLatch(numRequests); 
for (int i=0; i < numRequests; i++) {

     executor.submit(new util.Request(new URL(url), latch));
}
latch.await(someValue, TimeUnit.SECONDS)

` Edit

Re-implement util.Request doing something like

 public class Request implements Callable<Response> {
  final private URL url;
  final private CountDownLatch latch;

  public Request(URL url, CountDownLatch latch) {
      this.url = url;
      this.latch = latch;
  }

  @Override
  public Response call() throws Exception {

       try {
          return new Response(url.openStream());
       } 
       catch (Exception e) {

          //do something useful
       }
       finally {
          latch.countDown();
       }
  }
}

You may want to consume the stream of you response before you countDown the latch to verify that you get what you expect as a response from your server.

Autres conseils

If you are using this program to perform a load test, or even otherwise, I'd highly recommend that you use Jmeter instead. Jmeter already does what you are attempting to do and there are many plugins that will allow you to schedule the load / number of thread / time period etc. You can also monitor all HTTP requests through a variety of graphs.

Writing a test for your servlet should take you less than 5 minutes. The graphs are also easy to generate.

jmeter graph

If you'd still like to use your custom program to contact the servlet, you can always limit the number of requests and back them up with a blocking queue through a threadpool executor.

Lastly, do not modify the servlet. You should be able to monitor it as a black box.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top