如何限制Jetty接受的连接数量?

Big*_*Ben 17 java jetty embedded-jetty

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

不幸的是,所有这些Connectors似乎只是继续并尽可能快地接受传入连接并将它们分派到配置的线程池.

我的问题是我在受限制的环境中运行,而且我只能访问8K文件描述符.如果我收到一堆连接,我可以快速耗尽文件描述符并进入不一致状态.

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

有更好的解决方案吗?

小智 12

线程池有一个与之关联的队列.默认情况下,它是无限的.但是,在创建线程池时,您可以提供一个基于它的有界队列.例如:

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

这似乎解决了我的问题.否则,对于无限制队列,服务器在重负载下启动时会用完文件句柄.


Big*_*Ben 10

我最终得到了一个解决方案,它跟踪请求的数量,并在负载过高时发送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);
    }

}
Run Code Online (Sandbox Code Playgroud)


Sen*_*hil 5

我还没有为我的应用程序部署Jetty.但是使用Jetty和其他一些开源项目进行部署.根据以上经验:连接器配置如下:

acceptors:专用于接受传入连接的线程数.

acceptQueueSize:在操作系统开始发送拒绝之前可以排队的连接请求数.

http://wiki.eclipse.org/Jetty/Howto/Configure_Connectors

您需要在配置中将它们添加到下面的块中

<Call name="addConnector">
  <Arg>
      <New class="org.mortbay.jetty.nio.SelectChannelConnector">
        <Set name="port"><SystemProperty name="jetty.port" default="8080"/></Set>
        <Set name="maxIdleTime">30000</Set>
        <Set name="Acceptors">20</Set>
        <Set name="confidentialPort">8443</Set>
      </New>
  </Arg>
</Call>
Run Code Online (Sandbox Code Playgroud)

  • 问题是,`Acceptors`只是尽可能快地将连接转储到队列上,然后再获取更多,因此永远不会达到操作系统限制. (2认同)

pro*_*oba 5

acceptQueueSize

如果我理解正确,这是一个较低级别的TCP设置,它控制服务器应用程序确实以比传入连接速率低的速率来接受(当服务器应用程序接受)时将跟踪的传入连接数量。请参阅http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html#ServerSocket(int,%20int)的第二个参数

这与Jetty QueuedThreadPool中排队的请求数完全不同。在该队列中排队的请求已经完全连接,并且正在等待线程在池中变为可用,然后可以开始处理它们。

我有一个类似的问题。我有一个受CPU约束的servlet(几乎没有I / O或等待状态,因此异步无济于事)。我可以轻松地限制Jetty池中的最大线程数,这样就可以避免线程切换开销。但是,我似乎无法限制排队请求的长度。这意味着随着负载的增加,响应时间分别增加,这不是我想要的。

我想如果所有线程都忙,并且已排队的请求数达到N,则为所有其他请求返回503或其他错误代码,而不是永远增加队列。

我知道我可以通过使用负载均衡器(例如haproxy)来限制同时请求到码头服务器的数量,但是仅使用码头可以做到吗?

PS写完此内容后,我发现了Jetty DoS过滤器,并且似乎可以将其配置为如果超出预配置的并发级别,则以503拒绝传入请求:-)