2

我想出了这个:

如果($prog->memcache){
    $r = $prog->memcache->get("ratelimit:{$_SERVER['REMOTE_ADDR']}");
    if(!empty($r)) $prog->errorClose('此 IP 已被标记为可能滥用。');
}

富();// 我们正在限制速率的东西...

if($prog->memcache)
    $prog->memcache->set("ratelimit:{$_SERVER['REMOTE_ADDR']}", 1, 0, 5);

对此有任何想法,如果在 Memcached 中找到 IP,睡眠几秒钟是否有益?

4

2 回答 2

1

似乎是一个很好的解决方案,但也许您可以使用 session_id() 而不是 ip 地址。这样,如果您要与路由器后面的人打交道,就不会阻止不锤击的人。尽管他们可以通过清除 cookie 轻松地重新生成 session_id,但他们可能需要更长的时间才能做到这一点,而不是仅仅等待 5 秒。您绝对不想在 PHP 脚本中休眠,因为它只会在休眠时阻止 PHP 进程。

您可以设置另一个 memcache 项目来跟踪他们在 1 小时内收到警告的次数,然后您可以做一些更严厉的事情,或者记录用户信息。

虽然可能最好尝试优化操作,这样它就不会那么昂贵(说起来容易做起来难)。

于 2010-03-25T14:59:04.437 回答
0

您可以使用令牌桶算法进行速率限制。我已经为你实现了:带宽限制/令牌桶

我还建议不要睡觉,因为您确实会阻止服务器的资源。只需使用 HTTP 状态码 429 退出:

use bandwidthThrottle\tokenBucket\Rate;
use bandwidthThrottle\tokenBucket\TokenBucket;
use bandwidthThrottle\tokenBucket\storage\MemcachedStorage;

$storage = new MemcachedStorage("resource", $memcached);
$rate    = new Rate(10, Rate::SECOND);
$bucket  = new TokenBucket(10, $rate, $storage);
$bucket->bootstrap(10);

if (!$bucket->consume(1, $seconds)) {
    http_response_code(429);
    header(sprintf("Retry-After: %d", floor($seconds)));
    exit();
}

foo();

但是如果你真的想睡觉,你可以这样做BlockingConsumer

$consumer = new BlockingConsumer($bucket);
$consumer->consume(1);
foo();
于 2015-07-12T18:51:01.153 回答