如何在PHP中观察速率限制


How do I observe a rate Limit in PHP?

因此,我正在从API请求数据。到目前为止,我的API密钥仅限于:

每10秒10个请求每10分钟500个请求

基本上,我想从用户玩过的每一个游戏中请求一个特定的值。例如,大约有300场比赛。

所以我不得不用我的PHP发出300个请求。我如何才能让他们放慢速度以遵守利率限制?(这可能需要时间,站点不必很快)

我尝试sleep(),结果导致我的脚本崩溃。。还有其他方法吗?

我建议设置一个每分钟执行一次的cron作业,或者更好地使用Laravel调度,而不是使用sleep或usleep来模仿cron。

以下是两者的一些信息:

https://laravel.com/docs/5.1/scheduling

http://www.cyberciti.biz/faq/how-do-i-add-jobs-to-cron-under-linux-or-unix-oses/

这听起来像是对set_time_limit()函数的完美使用。此函数允许您指定脚本可以执行的时间(以秒为单位)。例如,如果在脚本开头说set_time_limit(45);,那么脚本将总共运行45秒。这个函数的一个伟大特性是,您可以通过说:set_time_limit(0);来允许脚本无限期地执行(没有时间限制)。

您可能希望使用以下通用结构编写脚本:

<?php
// Ignore user aborts and allow the script
// to run forever
ignore_user_abort(true);
set_time_limit(0);
// Define constant for how much time must pass between batches of connections:
define('TIME_LIMIT', 10); // Seconds between batches of API requests
$tLast = 0;
while( /* Some condition to check if there are still API connections that need to be made */ ){
    if( timestamp() <= ($tLast + TIME_LIMIT) ){ // Check if TIME_LIMIT seconds have passed since the last connection batch
        // TIME_LIMIT seconds have passed since the last batch of connections
        /* Use cURL multi to make 10 asynchronous connections to the API */
        // Once all of those connections are made and processed, save the current time:
        $tLast = timestamp();
    }else{
        // TIME_LIMIT seconds have not yet passed
        // Calculate the total number of seconds remaining until TIME_LIMIT seconds have passed:
        $timeDifference = $tLast + TIME_LIMIT - timestamp();
        sleep( $timeDifference ); // Sleep for the calculated number of seconds
    }
} // END WHILE-LOOP
/* Do any additional processing, computing, and output */
?>

注意:在这个代码片段中,我还使用了ignore_user_abort()函数。如代码注释中所述,此函数只允许脚本忽略用户中止,因此,如果用户在脚本仍在执行时关闭浏览器(或连接),脚本将继续从API检索和处理数据。您可能想在实现中禁用它,但我将把它留给您。

显然,这段代码非常不完整,但它应该让您对如何实现此问题的解决方案有一个很好的了解。

不要放慢单个请求的速度。

相反,您通常会使用Redis之类的东西来跟踪每个IP或每个用户的请求。一旦在一段时间内达到限制,则拒绝(可能使用HTTP 429状态代码),直到计数重置。

http://redis.io/commands/INCR外加http://redis.io/commands/expire很容易就能做到。