如何使用PHP限制API请求

时间:2012-12-10 21:47:39

标签: php api batch-processing

我们计划使用SEMrush API,它允许访问与域名和搜索关键字相关的SEO数据。在他们的Terms of Use下,他们限制了他们的使用,以避免杀死他们的服务器:

  

每秒执行的请求数不得超过10个,同时请求数不得超过2个。

我们将在PHP中构建一个简单的工具,该工具基于域名聚合数据,并且正在寻找有关如何满足该要求的基础知识。我们正在计划成百上千的潜在用户。

也许有人可以在PHP中提供一些让我们这样做的伪代码 - 或者它真的就像迫使实际的API请求函数在每个命令之间休眠1秒一样简单吗?我没有很多API和大量并发用户的经验,所以感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

PHP实际上不是用于并发编程的最佳语言。但是,您可以使用一些第三方解决方案来帮助您实现目标。

您需要的是一个可以处理实际请求的作业管理器或队列系统。由于这是一个后端工具(至少是我从你的问题中收集的),它不需要PHP来处理对作业本身的实际控制,而只是让一些控制进程安排这些单个作业并将它们交给您的PHP脚本,以便您可以有效地施加这些限制。

我的第一个建议是尝试类似gearman的内容,这是一位出色的职位经理,并且extension in PHP可以帮助您与图书馆进行交互。

另一个建议是查看amqpzmq等队列系统,其中一些系统也有extensions in PHP

所以这是你的一个示例场景......

您有一个接受这些请求的PHP脚本,并将它们交给您的作业管理器或通过套接字排队。作业管理器或队列将存储请求并以可以集中和控制以强加这些限制的方式将其分发给各个工作人员。我给你的链接中有一些例子可以帮助你实现目标。但是,如果不经过精心设计和考虑,在没有这些工具的帮助下纯粹在PHP中完成它将会非常棘手,如果不仔细制作和考虑,可能会出现一些非常边缘的错误行为。

答案 1 :(得分:0)

某些 API 在响应标头中返回速率限制信息。 查看: Examples of HTTP API Rate Limiting HTTP Response headers 此信息将帮助您等待几纳秒,然后使用 PHP 的 time_nanosleep()

继续您的下一个请求

一些 PHP 库非常深入地使用了它们的速率限制方法。 Bucket Token 算法在网络上很常见: https://github.com/bandwidth-throttle/token-bucket

现在我发现这在限制某些返回标头中没有 X-RateLimit-Remaining 之类的 URL 请求时有点过头了。 API 请求通常很慢。所以我在下面构建了 PHP 脚本。

此 PHP 脚本将根据 $throttlerID 等待几毫秒。较高的 requestsInSeconds 将导致更短的等待时间...如果在同时请求中使用相同的 $throttlerID,每个请求将使用文件锁定 (FLOCK()) 等待另一个请求。

    function Throttler($requestsInSeconds, $throttlerID) {

        // Use FLOCK() to create a system global lock (it's crash-safe:))
        $fp = fopen(sys_get_temp_dir()."/$throttlerID", "w+");

        // exclusive lock will blocking wait until obtained
        if (flock($fp, LOCK_EX)) { 

             // Sleep for a while (requestsInSeconds should be 1 or higher)
             $time_to_sleep = 999999999 / $requestsInSeconds; 
             time_nanosleep(0, $time_to_sleep);
    
             flock($fp, LOCK_UN); // unlock
         }

        fclose($fp);

    }

在每次 Throttler() 调用之前立即调用 CURL。就这样!