管理Tomcat每个Servlet的请求

3

我希望能从社区中获得一些最佳实践指导。

今天我正在管理一个Java Web应用程序。我们使用Tomcat作为容器,总共有大约50个servlet。其中大部分是标准的HttpServlet的扩展,并且没有更新以利用Servlet 3.X规范的任何新异步处理能力。这些servlet驱动着各种UI通信、客户端设备通信等等。

我们希望解决的问题是:一个servlet的请求过多可能会使其他servlet无法响应。这有两个方面。首先,过多的请求可能会消耗100%的系统资源,并使系统无响应。我们可以对这些请求进行限流和调整,使其消耗更少的资源,但这通常会导致连接池积压。无论哪种情况,我们最终都会发现其他servlet无响应。

我们目前正在研究的解决方案包括利用Servlet 3.0的异步功能和线程池来支持应用程序的不同领域。首先,这将使我们能够更好地调整应用程序以适应不同类型的请求。其次,这将使我们能够评估请求的类型并根据需要设置优先级。我们总是会有资源限制,至少这种方法可以让我们处理最重要的工作。

我们正在讨论的一个理论难点是,在我们将所有内容转换为这种新方法之前(可能需要一段时间),传统的servlet和请求仍然可能导致应用程序饱和。

我对SO社区的具体问题是...

  1. 在我们朝着这个机制努力的同时,是否有任何方法可以按servlet分别限制请求以防止饱和?
  2. 有关此类转换的“最佳实践”是否有任何资源可用?
  3. 我们期望达到的状态是否存在任何陷阱?如果存在,你有什么建议来减轻它们?

最后,我确实意识到,在大规模的情况下,这是处理许多不同类型请求的单个单块应用程序的副产品。我们目前正在进行一项努力,即将应用程序模块化,并可能使我们达到一个可以在不同系统之间分配应用程序的点。

谢谢!

2个回答

1
如果我可以提出一个不那么离题的答案,您可以为不同的执行器分配不同的优先级。
需要进行测试以确定收益是否真实和良好,但如果您能够负担得起两次应用程序运行(每个执行器运行一次),这可能是一个临时解决方案。有罪的servlet将由最低优先级Executor处理,而所有其他servlet将由最高优先级处理。
我看到有不同的实现方式。通过更改web.xml来隐藏应用程序1中的servlet并转发到应用程序2,或者通过实现过滤器来拦截对此有罪的servlet的调用,然后将其发送到第二个应用程序等。

喜欢这个想法!我们当前情况的另一个缺点是,我们为客户发布了一个WAR文件在现场运行。因此,配置开销和2倍的资源开销使得这个过程非常困难,但是对于创新解决方案表示赞赏。我们一定会尝试实验它! - Staros

0
为了在每个servlet上限制请求,可以使用一个过滤器来匹配特定的servlet名称,并允许仅同时处理一定数量的请求。
从servlet 2.5规范中:

在容器的JVM中,每个部署描述符中的<filter>声明仅实例化一次

在您的过滤器内,您可以使用信号量来限制请求。

ConcurrentRequestLimiter.java

private final int MAX_CONCURRENT_REQUESTS = 5;
private final Semaphore limiter = new Semaphore(MAX_CONCURRENT_REQUESTS);
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain)
        throws IOException, ServletException {
    try {
        if (!limiter.tryAcquire(0, TimeUnit.SECONDS)) {
            PrintWriter out = response.getWriter();
            try {
                out.print("System busy. Please try again later..");
            } finally {
                out.close();
            }
        }else{                
            try{
                chain.doFilter(request, response);
            }finally{
                limiter.release();
            }

        }
    } catch (InterruptedException ex) {/*Should never happen*/throw new ServletException("System inconsistency");}
}

web.xml

<filter>
    <filter-name>ConcurrentRequestLimiter</filter-name>
    <filter-class>ConcurrentRequestLimiter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ConcurrentRequestLimiter</filter-name>
    <url-pattern>/FilteredRequest</url-pattern>
</filter-mapping>
<servlet>
    <servlet-name>FilteredRequest</servlet-name>
    <servlet-class>FilteredRequest</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>FilteredRequest</servlet-name>
    <url-pattern>/FilteredRequest</url-pattern>
</servlet-mapping>

注意:如果您希望为不同的servlet使用不同的阈值,您可以使用不同的别名多次声明过滤器,并将num-concurrent-requests作为配置参数传递给它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接