我实现了一个穷人的节流机制 https://github.com/alixaxel/phunction/blob/23682aca0adaed23c676623ca1acfb82bb5f71a6/_.php#L501 in 漏音 https://github.com/alixaxel/phunction/blob/master/_.php单独使用APC,这就是我的使用方式:
// allow 60 requests every 30 seconds
// each request counts as 1 (expensive operations can use higher values)
// keep track of IPs by REMOTE_ADDR (ignore others)
$throttle = ph()->Throttle($ttl = 30, $exit = 60, $count = 1, $proxy = false);
if ($throttle === true)
{
// IP exceded 30 requests in the last 60 seconds, die() here
}
else
{
// $throttle is a float
// number of requests in the last 30 seconds / 30 seconds
/*
1 req / 30 = 0,033 sec
5 req / 30 = 0,166 sec
10 req / 30 = 0,333 sec
15 req / 30 = 0,5 sec
20 req / 30 = 0,666 sec
25 req / 30 = 0,833 sec
30 req / 30 = 1 sec
*/
usleep(intval(floatval($throttle) * 1000000));
}
我在我的前端控制器上使用它并将值传递给我的路由方法,但那是另一个故事了。
最重要的是,如果您使用 APC,您可以在内存中保持非常快的速度,并且几乎不消耗内存,因为 APC 遵循 FILO 方法。如果您需要更高的超时,您可以考虑使用不基于内存的东西。
顺便说一句:MySQL 支持带有 MEMORY 引擎的表。
问题在于sleep()
:
作为模块安装 PHP 的典型 Apache Web 服务器每个实例将占用大约 10 MB 的 RAM,为了避免超出可用 RAM,您可以配置一些 Apache 设置来限制 Apache 能够启动的最大实例数量。
问题是当你sleep()
,该实例仍然处于活动状态,并且有足够的请求可能最终会耗尽所有可用插槽来启动新服务器,从而使您的网站无法访问,直到某些待处理的请求完成。
PHP AFAIK 没有办法克服这个问题,所以最终取决于你。
系统范围的节流原理是相同的:
function systemWide($ttl = 86400, $exit = 360)
{
if (extension_loaded('apc') === true)
{
$key = array(__FUNCTION__);
if (apc_exists(__FUNCTION__) !== true)
{
apc_store(__FUNCTION__, 0, $ttl);
}
$result = apc_inc(__FUNCTION__, 1);
if ($result < $exit)
{
return ($result / $ttl);
}
return true;
}
return false;
}