How to set limit to the number of concurrent request in servlet?

Solution 1:

I'd suggest writing a simple servlet Filter. Configure it in your web.xml to apply to the path that you want to limit the number of concurrent requests. The code would look something like this:

public class LimitFilter implements Filter {
    private int limit = 5;
    private int count;
    private Object lock = new Object();

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        try {
            boolean ok;
            synchronized (lock) {
                ok = count++ < limit;
            }
            if (ok) {
                // let the request through and process as usual
                chain.doFilter(request, response);
            } else {
                // handle limit case, e.g. return status code 429 (Too Many Requests)
                // see https://www.rfc-editor.org/rfc/rfc6585#page-3
            }
        } finally {
            synchronized (lock) {
                count--;
            }           
        }
    }
}

Or alternatively you could just put this logic into your HttpServlet. It's just a bit cleaner and more reusable as a Filter. You might want to make the limit configurable through the web.xml rather than hard coding it.

Ref.:
Check definition of HTTP status code 429.

Solution 2:

You can use RateLimiter. See this article for explanation.

Solution 3:

You might want to have a look on Semaphore.

Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.

Or even better try to figure it out with the server settings. That would of course be server-dependant.

Solution 4:

I've thought about using a static counter to keep track of the number of request, but it would raise a problem of race condition.

If you use a AtomicInteger for the counter, you will not have the problem of race conditions.

An other way would be using the Java Executor Framework (comes with Java 1.5). There you are able to limit the number of running threads, and block new once until there is a new free thread.

But I think the counter would work and be the easyest solution.

Attention: put the counter relese in a finally block!

//psydo code
final AtomicInteger counter;
...
while(true) {
  int v = counter.getValue()
  if (v > max) return FAILURE;
  if(counter.compareAndSet(v, v+1)) break;  
}
try{
  doStuff();
} finally{
  counter.decrementAndGet();
}