防止客户端超载服务器?

时间:2011-02-09 02:36:51

标签: java servlets request

我有一个Java servlet在高峰时段因客户端请求而过载。一些客户端跨越并发请求。有时每秒的请求数量太多了。

我应该实现应用程序逻辑来限制请求客户端每秒可以发送的数量吗?这是否需要在应用程序级别完成?

3 个答案:

答案 0 :(得分:1)

处理此问题的两种最常见的方法是在服务器太忙时关闭请求,或者将每个请求放慢速度。

转移请求很容易;只运行固定数量的实例。操作系统可能会也可能不会排队一些连接请求,但通常用户将无法连接。更优雅的方法是让服务返回一个错误代码,表明客户端应该稍后再试。

处理请求的速度要慢一些,因为它需要将处理请求的servlet与在不同线程中执行工作的类分开。您可以拥有比工蜂更多的servlet。当一个请求进来时,它接受它,等待一个工蜂,抓住它并使用它,释放它,然后返回结果。

这两个人可以通过java.util.concurrent中的一个类进行通信,例如LinkedBlockingQueueThreadPoolExecutor。如果你想变得非常花哨,你可以使用类似PriorityBlockingQueue之类的东西来为其他客户服务。

我,我会像Anon所说的那样投入更多硬件;)

答案 1 :(得分:1)

这里有一些可靠的答案。我认为更多的硬件是要走的路。拥有太多客户端或流量通常是一个很好的问题。

但是,如果你绝对必须限制客户,那么有一些选择。

我见过的最具扩展性的解决方案围绕分布式缓存系统,如Memcached,并使用整数来保持计数。

计算系统处理流量的速率。无论是整体还是每个客户。然后将计数放入表示该速率的memcached中。每次收到请求时,都会减少该值。定期增加计数器以允许更多流量通过。

例如,如果您可以处理10个请求/秒,则每5秒钟计数50个,最多50个。这样您就不会一直重新填充它,但您也可以处理爆炸的一点限于一个窗口。您需要尝试找到一个良好的刷新率。此计数器的密钥可以是全局密钥,也可以基于用户ID,如果您需要限制该方式。

这个系统的优点是它可以在整个集群中运行,并且重新填充计数器的机制不需要在当前的一个服务器中。您可以为其专门设置一个流程。加载的服务器只需要检查并减少它。

所有这一切,我先调查其他选项。限制客户通常是一种惹恼他们的好方法。最可能不是最好的主意。 :)

答案 2 :(得分:1)

我假设您无法通过硬件或软件增加容量,而且您只需要限制服务器上的外部负载。

应避免在应用程序中处理此问题,除非您有非常特殊的需求,而这些需求是在HTTP服务器级别运行的现有解决方案所不能满足的。很多想法已经解决了这个问题,因此值得研究现有的解决方案,而不是自己实现。

如果您正在使用Tomcat,则可以配置通过maxThreads和acceptCount设置允许的最大并发请求数。请阅读http://tomcat.apache.org/tomcat-6.0-doc/config/http.html上的简介,了解有关这些内容的更多信息。

对于更高级的控件(如每用户限制),如果您通过Apache代理,则可以使用各种模块来帮助处理这种情况。谷歌的一些模块是limitipconn,mod_bw和mod_cband。这些设置和理解比你的appserver可能提供的基本控件要难得多,所以你可能只想坚持使用它们。