带宽节流/令牌桶延迟(PHP)

时间:2016-05-03 11:39:38

标签: php throttling

我将https://github.com/bandwidth-throttle/token-bucket用于仅限于外部服务器的查询。 我的代码:

function main() {
    unlink(__DIR__ . "/api.bucket2");
    $storage  = new FileStorage(__DIR__ . "/api.bucket2");
    $rate     = new Rate(3, Rate::SECOND);
    $bucket   = new TokenBucket(3, $rate, $storage);
    $bucket->bootstrap(3);
    $consumer = new BlockingConsumer($bucket);

    for ($i = 0; $i < 12; $i++) {
        $consumer->consume(1);

        work();
    }
}

function work() {
    echo date("d.m.Y H:i:s") . substr((string)microtime(), 1, 4) . "\n";
}

main();

结果:

-bash-4.2$ php -f worker-test.php
03.05.2016 14:26:16.785
03.05.2016 14:26:16.785
03.05.2016 14:26:16.786
03.05.2016 14:26:17.118
03.05.2016 14:26:17.451
03.05.2016 14:26:17.784
...

我预计该函数每秒会被调用3次,但事实并非如此。前6个电话是1秒钟。如果我改变&#34; $ bucket-&gt; bootstrap(3); &#34; on&#34; $ bucket-&gt; bootstrap(0);&#34;,它会更好:

03.05.2016 14:33:34.913
03.05.2016 14:33:35.245
03.05.2016 14:33:35.578
03.05.2016 14:33:35.911
...

但它仍然超过每秒3次。我做错了什么?

1 个答案:

答案 0 :(得分:2)

$bucket->bootstrap(3);

TokenBucket::bootstrap(3)将三个初始令牌放入存储桶中。那些初始令牌可以立即消费。你实际上不会限制第一次通话的费率。

如果你不想要那个初始爆发,那你就没有任何标记进行了正确的自举。

03.05.2016 14:33:34.913
03.05.2016 14:33:35.245
03.05.2016 14:33:35.578
03.05.2016 14:33:35.911
     

但它仍然超过每秒3次。

我每秒数3。请容忍这种观察到的±1ms的方差。从长远来看,你平均每秒可以获得3次。

这±1ms可能来自BlockingConsumer的{​​{3}}:

// sleep at least 1 millisecond.
usleep(max(1000, $seconds * 1000000));