java 如何在servlet中设置并发请求数限制?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5563442/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:40:54  来源:igfitidea点击:

How to set limit to the number of concurrent request in servlet?

javaservlets

提问by lamwaiman1988

I got this servlet which return a pdf file to the client web browser. We do not want to risk any chance that when the number of request is too much, the server is paralyzed.

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

We would like to make an application level (program) way to set a limit in the number of concurrent request, and return a error message to the browser when the limit is reached. We need to do it in applicantion level because we have different servlet container in development level(tomcat) and production level(websphere).

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

I must emphasize that I want to control the maximum number of request instead of session. A user can send multiple request over the server with the same session.

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

Any idea? I've thought about using a static counter to keep track of the number of request, but it would raise a problem of race condition.

任何的想法?我曾考虑使用静态计数器来跟踪请求的数量,但这会引发竞争条件问题。

回答by WhiteFang34

I'd suggest writing a simple servlet Filter. Configure it in your web.xmlto apply to the path that you want to limit the number of concurrent requests. The code would look something like this:

我建议编写一个简单的 servlet Filter。在你的配置中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--;
            }           
        }
    }
}

Or alternatively you could just put this logic into your HttpServlet. It's just a bit cleaner and more reusable as a Filter. You might want to make the limit configurable through the web.xmlrather than hard coding it.

或者,您可以将此逻辑放入您的HttpServlet. 作为Filter. 您可能希望通过web.xml而不是硬编码来配置限制。

Ref.:
Check definition of HTTP status code 429.

参考:
检查HTTP 状态代码 429 的定义。

回答by Ivan Ursul

You can use RateLimiter. See thisarticle for explanation.

您可以使用 RateLimiter。请参阅这篇文章的解释。

回答by Ralph

I've thought about using a static counter to keep track of the number of request, but it would raise a problem of race condition.

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

If you use a AtomicInteger for the counter, you will not have the problem of race conditions.

如果您使用 AtomicInteger 作为计数器,则不会出现竞争条件的问题。

An other way would be using the Java Executor Framework(comes with Java 1.5). There you are able to limit the number of running threads, and block new once until there is a new free thread.

另一种方法是使用Java Executor Framework(Java 1.5 附带)。在那里您可以限制正在运行的线程数,并阻止新线程一次,直到有新的空闲线程。

But I think the counter would work and be the easyest solution.

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

Attention: put the counter relese in a finally block!

注意:将计数器 relese 放在 finally 块中!

//psydo code
final AtomicInteger counter;
...
while(true) {
  int v = counter.getValue()
  if (v > max) return FAILURE;
  if(counter.compareAndSet(v, v+1)) break;  
}
try{
  doStuff();
} finally{
  counter.decrementAndGet();
}

回答by Jan Zyka

You might want to have a look on Semaphore.

您可能想看看Semaphore

Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource.

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

Or even better try to figure it out with the server settings. That would of course be server-dependant.

或者甚至更好地尝试通过服务器设置来解决这个问题。这当然取决于服务器。

回答by irreputable

If you are serving static files, it's unlikely that the server will crash. The bottleneck would be the network throughput, and it degrades gracefully - when more requests come in, each still get served, just a little bit slower.

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

If you set a hard limit on total requests, remember to set a limit on requests per IP. Otherwise, it's easy for one bad guy to issue N requests, deliberately read the responses very slowly, and totally clog your service. This works even if he's on a dialup and your server network has a vast throughput.

如果您对总请求数设置了硬限制,请记住对每个 IP 的请求数设置限制。否则,一个坏人很容易发出 N 个请求,故意非常缓慢地读取响应,并完全阻塞您的服务。即使他正在拨号并且您的服务器网络具有巨大的吞吐量,这也有效。