簡體   English   中英

用PHP&Memcached限制昂貴的操作速率的最佳方法是什么?

[英]What's the best approach to rate limit an expensive operation with 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);

對此有任何想法,如果在Memcached中找到IP,睡眠幾秒鍾是否有益?

似乎是一個很好的解決方案,盡管也許可以使用session_id()代替ip地址。 這樣,如果您與路由器背后的人打交道,就不會阻止那些不會重錘的人。 盡管可以通過清除cookie輕松地重新生成session_id,但這樣做可能要花更長的時間,而不僅僅是等待5秒鍾。 您絕對不想睡在PHP腳本中,因為那樣只會在睡着時阻止PHP進程。

您可以設置另一個內存緩存項,以跟蹤它們在1小時內達到警告次數的次數,然后您可以執行更苛刻的操作或記錄用戶信息。

盡管可能最好嘗試優化操作,以免成本高昂(說起來容易做起來難)。

您可以將令牌桶算法用於速率限制。 我已經為您實現了: 帶寬限制/令牌桶

我也建議不要睡眠,因為這會阻塞服務器資源。 只需使用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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM