Java 如何设置servlet中并发请求数的限制?

Java 如何设置servlet中并发请求数的限制?,java,servlets,Java,Servlets,我得到了这个servlet,它将一个pdf文件返回到客户端web浏览器。 我们不想冒任何风险,当请求数量过多时,服务器会瘫痪 我们希望使用应用程序级(程序)方法来设置并发请求数量的限制,并在达到限制时向浏览器返回错误消息。我们需要在应用程序级别执行此操作,因为我们在开发级别(tomcat)和生产级别(websphere)有不同的servlet容器 我必须强调,我希望控制请求的最大数量,而不是会话。用户可以使用同一会话通过服务器发送多个请求 有什么想法吗? 我曾考虑过使用静态计数器来跟踪请求的数量

我得到了这个servlet,它将一个pdf文件返回到客户端web浏览器。 我们不想冒任何风险,当请求数量过多时,服务器会瘫痪

我们希望使用应用程序级(程序)方法来设置并发请求数量的限制,并在达到限制时向浏览器返回错误消息。我们需要在应用程序级别执行此操作,因为我们在开发级别(tomcat)和生产级别(websphere)有不同的servlet容器

我必须强调,我希望控制请求的最大数量,而不是会话。用户可以使用同一会话通过服务器发送多个请求

有什么想法吗? 我曾考虑过使用静态计数器来跟踪请求的数量,但这会引起竞争条件的问题

我曾考虑过使用静态计数器来跟踪请求的数量,但这会引起竞争条件的问题

如果计数器使用AtomicInteger,则不会出现争用条件问题

另一种方法是使用(Java1.5附带)。在这里,您可以限制正在运行的线程的数量,并阻止new一次,直到有一个新的空闲线程

但我认为计数器会起作用,是最简单的解决方案

注意:将计数器放在最后一块


你可能想看看

信号量通常用于限制可以访问某些(物理或逻辑)资源的线程数


或者最好尝试使用服务器设置来解决这个问题。这当然取决于服务器。

我建议编写一个简单的servlet
过滤器。在
web.xml
中配置它以应用于要限制并发请求数量的路径。代码如下所示:

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 http://tools.ietf.org/html/rfc6585#page-3
            }
        } finally {
            synchronized (lock) {
                count--;
            }           
        }
    }
}
公共类LimitFilter实现过滤器{
私有整数限制=5;
私人整数计数;
私有对象锁=新对象();
public void doFilter(ServletRequest请求、ServletResponse响应、,
FilterChain链)抛出IOException、ServletException{
试一试{
布尔ok;
已同步(锁定){
ok=计数++<极限;
}
如果(确定){
//让请求通过并像往常一样处理
链式过滤器(请求、响应);
}否则{
//处理限制情况,例如返回状态代码429(请求过多)
//看http://tools.ietf.org/html/rfc6585#page-3
}
}最后{
已同步(锁定){
计数--;
}           
}
}
}
或者,您也可以将此逻辑放入
HttpServlet
。它只是稍微干净一点,并且作为
过滤器更易于重用。您可能希望通过
web.xml
对限制进行配置,而不是对其进行硬编码

参考:

检查的定义。

如果您提供的是静态文件,则服务器不太可能崩溃。瓶颈将是网络吞吐量,它会优雅地下降——当更多的请求进来时,每个请求仍然得到服务,只是稍微慢一点


如果对总请求设置了硬限制,请记住对每个IP的请求设置限制。否则,一个坏蛋很容易发出N个请求,故意以非常慢的速度阅读响应,并完全阻塞您的服务。即使他正在拨号,并且您的服务器网络具有巨大的吞吐量,这种方法也能起作用

您可以使用RateLimitor。有关解释,请参阅文章。

看起来它回答了问题-您使用的是哪台服务器?Sempahores将不适用于此,因为如果信号量低于0,将阻止请求。但在这种情况下,要求发送一条错误消息。@Ralph:它可以与
tryAcquire()
一起工作,但这太过分了。我不认为使用经过良好测试的库软件(
Semaphore
)太过分了。@WhiteFang34,你能发布你以前的解决方案吗?我想看看拉尔夫说了什么。我更喜欢使用简单的计数器。小型比赛的条件可以忽略,我不在乎是否有人需要等待…@gunbuster363:它在比赛中。不过最新的还是一个简单的计数器。我担心synchronize()方法会使自己成为程序的瓶颈。@gunbuster363:同步并不是围绕整个请求进行的(这肯定不起作用,它会将其限制为一个并发请求)。只是在检查周围看看是否达到了极限。它非常短,开销非常小。多年来,我一直在使用一个更复杂的版本,效果非常好。试一试,让servlet睡眠10秒钟,然后发出一堆请求。只有5个(或您的限制)将同时运行。@WhiteFang34 hey folk。。我试过这个,效果很好。我想问你,如果假设我想设置,如果并发请求的数量不超过5000;然后它应该返回429状态代码。此外,限额改为5000,检查是否足够,这只是一种预防措施。“如果”请求能够使网络瘫痪,我们有责任限制传入请求的数量。你知道吗?
计数器是否应该是
易失性的
?@asgs计数器应该是
最终的
,因为它不是要重新分配的,那么不需要易失性的,只需从末尾删除/字符即可。试试这个。
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 http://tools.ietf.org/html/rfc6585#page-3
            }
        } finally {
            synchronized (lock) {
                count--;
            }           
        }
    }
}