2010-03-25 35 views
2

我想出了這一點:用PHP和Memcached限制昂貴操作的最佳方法是什麼?

 
if($prog->memcache) { 
    $r = $prog->memcache->get("ratelimit:{$_SERVER['REMOTE_ADDR']}"); 
    if(!empty($r)) $prog->errorClose('This IP has been flagged for potential abuse.'); 
} 

foo(); // the thing we're rate limiting... 

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

對此有何想法,這將是有益的睡了幾秒鐘,如果IP地址在Memcached中發現了什麼?

回答

1

看起來像一個很好的解決方案,但也許你可以使用session_id()而不是ip地址。這樣,如果你與路由器後面的人打交道,你不會阻止那些沒有敲打的人。雖然session_id可以很容易地通過清除cookie來重新生成,但它可能需要更長的時間才能完成,而不是等待5秒鐘。你絕對不想睡在一個PHP腳本中,因爲它只是在睡覺時支持一個PHP進程。

您可以設置另一個內存緩存項目來跟蹤他們在1小時內發出警告的次數,然後您可以做更嚴厲的事情或記錄用戶信息。

雖然可能是最好的嘗試優化操作,所以它不是成本高(說起來容易做起來難)。

+0

謝謝,我知道我可以做多一點,但我真的需要快速和骯髒的東西。 – mmattax 2010-03-25 15:44:16

0

您可以使用token bucket algorithm進行速率限制。我已經爲你實現了:bandwidth-throttle/token-bucket

我也建議不要睡覺,因爲你會阻止服務器的資源。

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做到這一點:只要用HTTP狀態代碼429退出

$consumer = new BlockingConsumer($bucket); 
$consumer->consume(1); 
foo(); 
相關問題