如何限制码头接受的转机次数?

2022-09-02 20:29:08

我正在运行Jetty 7.2.2,并希望限制它将处理的连接数,这样当它达到限制(例如5000)时,它将开始拒绝连接。

不幸的是,所有这些似乎都只是继续以最快的速度接受传入连接,并将它们分派到配置的线程池。Connectors

我的问题是我在受约束的环境中运行,并且我只能访问8K文件描述符。如果我收到一堆连接,我可以很快用完文件描述符并进入不一致的状态。

我的一个选择是返回HTTP,但这仍然需要我接受并响应连接 - 并且我会通过编写servlet过滤器来跟踪某个地方的传入连接的数量。503 Service Unavailable

有没有更好的解决方案?


答案 1

线程池具有与之关联的队列。默认情况下,它是无限的。但是,在创建线程池时,您可以提供有界队列作为其基础。例如:

Server server = new Server();
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(maxQueueSize);
ExecutorThreadPool pool = new ExecutorThreadPool(minThreads, maxThreads, maxIdleTime, TimeUnit.MILLISECONDS, queue);
server.setThreadPool(pool);

这似乎为我解决了问题。否则,对于无界队列,服务器在负载过重时会耗尽文件句柄。


答案 2

我最终选择了一个解决方案,该解决方案可以跟踪请求的数量,并在负载过高时发送503。这并不理想,正如你所看到的,我必须添加一种方法来始终让延续请求通过,这样他们就不会挨饿。很好地满足我的需求:

public class MaxRequestsFilter implements Filter {

    private static Logger cat   = Logger.getLogger(MaxRequestsFilter.class.getName());

    private static final int DEFAULT_MAX_REQUESTS = 7000;
    private Semaphore requestPasses;

    @Override
    public void destroy() {
        cat.info("Destroying MaxRequestsFilter");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        long start = System.currentTimeMillis();
        cat.debug("Filtering with MaxRequestsFilter, current passes are: " + requestPasses.availablePermits());
        boolean gotPass = requestPasses.tryAcquire();
        boolean resumed = ContinuationSupport.getContinuation(request).isResumed();
        try {
            if (gotPass || resumed ) {
                chain.doFilter(request, response);
            } else {
                ((HttpServletResponse) response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
            }
        } finally {
            if (gotPass) {
                requestPasses.release();
            }
        }
        cat.debug("Filter duration: " + (System.currentTimeMillis() - start) + " resumed is: " + resumed);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

        cat.info("Creating MaxRequestsFilter");

        int maxRequests = DEFAULT_MAX_REQUESTS;
        requestPasses = new Semaphore(maxRequests, true);
    }

}

推荐