You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何限制Web API与Web应用的并发请求数?含代码实现疑问

Great question! Let's tackle this from both general strategies and concrete code implementation for your Java Servlet scenario.

如何限制Web API的并发请求数?

There are several practical approaches to control concurrent requests for a Web API, tailored to different tech stacks and needs:

  • Container-level configuration: Most servlet containers (like Tomcat, Jetty) let you set thread pool limits directly. For example, in Tomcat, adjust maxThreads and acceptCount in the connector settings to cap the number of concurrent processing threads.
  • Code-level control: Use concurrency utilities (like Java's Semaphore) or custom filters to enforce limits across all or specific endpoints. This gives you fine-grained control over which requests get throttled.
  • Reverse proxy/load balancer: Tools like Nginx allow you to set connection limits per upstream server, acting as a gatekeeper before requests reach your API.
如何通过代码将Web应用的并发请求数限制为3个?

For a Java Web application using Servlets, you don't need to wrap each servlet class in a separate thread—your servlet container (like Tomcat) already manages a thread pool to handle incoming requests. Instead, a global semaphore is a clean, efficient way to enforce the 3-concurrent limit across all requests (or specific endpoints).

Here's a concrete implementation using a Servlet Filter, which applies the limit globally:

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.util.concurrent.Semaphore;

@WebFilter("/*") // Applies to all endpoints in the app
public class ConcurrentRequestFilter implements Filter {
    // Global semaphore with 3 permits (one per allowed concurrent request)
    private static final Semaphore CONCURRENCY_SEMAPHORE = new Semaphore(3);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // No extra setup needed here
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            // Acquire a permit—blocks if all 3 are in use
            CONCURRENCY_SEMAPHORE.acquire();
            // Pass the request to the next filter or servlet
            chain.doFilter(request, response);
        } catch (InterruptedException e) {
            // Handle overload by returning a 503 error
            response.setContentType("text/plain");
            response.getWriter().write("Too many concurrent requests. Please try again later.");
            ((javax.servlet.http.HttpServletResponse) response).setStatus(503);
            Thread.currentThread().interrupt(); // Restore interrupt status for the thread
        } finally {
            // Release the permit no matter if the request succeeded or failed
            CONCURRENCY_SEMAPHORE.release();
        }
    }

    @Override
    public void destroy() {
        // No cleanup required for the semaphore
    }
}

If you only want to limit specific servlets instead of the entire app, you can initialize the semaphore directly in the servlet:

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.Semaphore;

@WebServlet("/limited-endpoint")
public class LimitedServlet extends HttpServlet {
    private Semaphore requestSemaphore;

    @Override
    public void init() throws ServletException {
        super.init();
        // Initialize semaphore with 3 permits for this specific servlet
        requestSemaphore = new Semaphore(3);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        try {
            requestSemaphore.acquire();
            // Your core servlet logic here
            resp.getWriter().write("Processing your request...");
        } catch (InterruptedException e) {
            resp.setStatus(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
            resp.getWriter().write("Too many concurrent requests to this endpoint.");
            Thread.currentThread().interrupt();
        } finally {
            requestSemaphore.release();
        }
    }
}
是否需要将每个servlet class放入thread中,并通过创建新类来实现global counter?

Short answer: No—here's why:

  • Servlet containers already manage a thread pool to handle incoming requests, so you don't need to manually wrap each servlet in a thread. The container handles threading automatically.
  • For a global counter, you don't need a dedicated new class. A static Semaphore (as shown above) acts as a built-in, thread-safe "counter" for concurrent permits. If you wanted a manual counter, you could use a static AtomicInteger with proper synchronization, but Semaphore is purpose-built for this use case and avoids manual sync errors.

Static variables in the filter/servlet are shared across all instances in the same classloader, so they naturally act as a global limit for your application.

内容的提问来源于stack exchange,提问作者student

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:04:20