2010-11-23 13 views
9

私はさまざまなサードパーティのWeb APIを使用していますが、その多くはレート制限を実施しています。非常に一般的なPHPライブラリを使用すると、私の呼び出しを制限することができます。私はそれを行ういくつかの方法を考えることができます。おそらくコールを発信できるタイムスタンプを持つキューにコールを入れることによって実現できますが、他の誰かが既にこのようにうまく行っていれば、PHPレート制限クライアント

+1

レート制限転送されたAPI呼び出しまたはバイト数? – stillstanding

+0

APIコールの数。 –

答えて

2

私はクレジットを取ることはできませんが、私はこのアプローチを「汎用」パッケージがなかったので使っていましたが、コーディングの方法に応じて変更できると思います。代替として

How do I throttle my site's API users?

+1

それはサーバ側に見えますが、私のAPIの他の人の使い方をどのように抑制するのか - 私は間違っていませんが、他の人のサーバに自分の呼び出しを絞り込む必要があります。 (クライアントサイドのようなコードスニペットを参照していない限り、実際に必要なものに近いことがあります) –

1

、私は(過去に)てきた私は、特定の時間範囲内で、再び同じコールを作ってみるので、もし、それをAPI呼び出しを格納されている「キャッシュ」フォルダを作成しましたキャッシュから最初に(もっとシームレスに)新しい電話をかけるまで。短期間でアーカイブされた情報に終わるかもしれませんが、長期的にあなたをブロックするAPIからあなたを救います。

+0

キャッシングは、同じパラメータで特定のAPIを呼び出す場合にのみ便利です。それは正しい方向への一歩ですが、私はしばしばパラメータを変え、異なる結果を期待しています。また、一部のAPIでは、TOSでのキャッシュを禁止しています。 –

5

これは古いスレッドだとわかりましたが、SE上で見つかった何か他のものに基づいていたので、私は自分のソリューションを投稿したいと思っていました。私は自分自身で答えを探していましたが、何か良いものを見つけるのが難しかったです。これは、hereで説明したPythonソリューションに基づいていますが、可変サイズのリクエストのサポートを追加し、PHPクロージャを使用して関数ジェネレータに変換しました。

function ratelimiter($rate = 5, $per = 8) { 
    $last_check = microtime(True); 
    $allowance = $rate; 

    return function ($consumed = 1) use (
    &$last_check, 
    &$allowance, 
    $rate, 
    $per 
) { 
    $current = microtime(True); 
    $time_passed = $current - $last_check; 
    $last_check = $current; 

    $allowance += $time_passed * ($rate/$per); 
    if ($allowance > $rate) 
     $allowance = $rate; 

    if ($allowance < $consumed) { 
     $duration = ($consumed - $allowance) * ($per/$rate); 
     $last_check += $duration; 
     usleep($duration * 1000000); 
     $allowance = 0; 
    } 
    else 
     $allowance -= $consumed; 

    return; 
    }; 
} 

これは何かを制限するために使用できます。ここではデフォルトで8秒あたり5「の要求を」シンプルな声明を制限愚かな例です:

$ratelimit = ratelimiter(); 
while (True) { 
    $ratelimit(); 
    echo "foo".PHP_EOL; 
} 

は、ここで私はベース600秒あたり600回のリクエストでFacebookのグラフAPIに対するバッチ処理要求を制限するためにそれを使用している方法ですバッチサイズ:

$ratelimit = ratelimiter(600, 600); 
while (..) { 
    .. 

    $ratelimit(count($requests)); 
    $response = (new FacebookRequest(
    $session, 'POST', '/', ['batch' => json_encode($requests)] 
))->execute(); 

    foreach ($response->..) { 
    .. 
    } 
} 

希望すると、誰かに役立ちます。

+0

ちょうど私が欲しかった。ありがとう! – 3zzy

+0

パーフェクト、ありがとう! –

4

token bucket algorithmでレート制限を行うことができます。 PHPであなたのために実装しました:bandwidth-throttle/token-bucket

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

$storage = new FileStorage(__DIR__ . "/api.bucket"); 
$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(); 
}