Apache中基于URL的请求速率限制

有很多速率限制和QoS工具,但到目前为止,我还没有find一个满足我的具体需求,如下所示:

我有一个在Apache 2.2上运行的Web应用程序,我希望我的每个客户被限制为每天10000个请求。 该限制不应该基于客户的IP地址,而是基于客户的帐户,这可以从URL中提取; 例如: http : //mywebsite.com/customer1/page1 。 一旦超过限制,我希望他们的请求被“放慢”到某个预定义的值,比如每分钟15个请求,也许会引入一个延迟。 如果这是不可能的,那么返回503服务不可用的错误就没问题。

我怎样才能做到这一点与Apache? 如果没有办法与Apache做,那么我会对其他工具,反向代理等的build议感兴趣。

更新:速率限制需要发生在一些服务(mod_dav_svn,mod_passenger,mod_wsgi),并且必须是高性能的。

我不认为你将能够纯粹在Apache中做到这一点。

有相当多的Apache模块可以进行带宽限制,但是我不认为它们中的任何一个都能满足您所描述的要求。

mod_bw可以根据请求的各个部分限制带宽。 它可以根据IP地址,文件扩展名,MIMEtypes,文件大小和目录(根据我对文档的阅读)进行限制。 通过将模块的指令放在一个<Directory >块中实现基于目录的限制,所以我期望它们能够在<Location >块中工作。 mod_bwshare似乎也进入<Directory ><Location >块。

这些Apache模块的configuration会进入Apacheconfiguration,并且不会从任何外部源查找值,这意味着您将不得不重新启动Apache以更改任何值。 如果您只想在客户超过配额时限制带宽,则需要编辑Apacheconfiguration文件,并在每次configuration文件都重新启动时重新启动Apache,并在配额使用过期时再次执行。

他们的方式我会这样做,就是写一个小的应用程序,无论你使用什么语言,接受一个文件的请求,检查数据库中的客户是否超过配额,然后以适当的速度发送文件。 写了mod_bw的人解释了他是如何实现节stream的:他只是简单地将文件分成小块(比如每个块5KB),然后在每个块向客户端回传之间有一个短暂的sleep()

然后,我将使用mod_rewrite将原始文件请求(您说的看起来像/customer1/page1 )翻译成/throttle.php?customer=customer1&file=page1类的/throttle.php?customer=customer1&file=page1

该应用程序可以在下载开始时写入数据库,以表明它正在处理一个文件,并在最后再次指出它现在已经完成。 这应该使你能够阻止一个客户占用你所有的Apache儿童。

我刚刚接受了@ Ladadadada的答案:“这不能用Apache来完成”,但是我想我会列出几个我正在寻找的方法,以供参考:

  1. 写我自己的Apache模块。 它将使用共享内存来跟踪所有的请求和他们的帐户。 这些计数将在24小时后过期。 超过下限的帐户会将其每个请求延迟一定的时间,超过上限的帐户将为所有请求返回503状态。 帐户名称将使用SetEnvIf从URL中提取。

  2. 编写一个脚本(在Ruby中),它将作为守护进程运行并停止Apache访问日志。 它会从每个logging的请求中提取帐户名称并跟踪它们,类似于#1,没有共享内存的复杂性。 它还会跟踪过去24小时内与给定账户相关的所有IP。 当帐户超过限制时,它会为与帐户关联的每个IP添加NFQUEUE iptables规则。 来自这些IP的数据包将被Ruby脚本使用Netfilter :: Queue(在第二个线程中)捕获,在那里它们将被延迟。