3

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

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

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

也许有人可以在 PHP 中提供一些伪代码来让我们这样做——或者它真的就像强制实际的 API 请求函数在每个命令之间休眠 1 秒一样简单吗?我在 API 和大量并发用户方面没有很多经验,因此不胜感激。

4

2 回答 2

2

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

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

我的第一个建议是尝试类似gearman的东西,它是一个很棒的工作管理器,并且有一个PHP 扩展来帮助您与库进行交互。

另一个建议是看看像amqpzmq这样的队列系统,其中一些在 PHP 中也有扩展

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

您有一个 PHP 脚本来接受这些请求并将它们交给您的作业管理器或通过套接字排队。作业管理器或队列将存储请求并以一种可以集中和控制的方式将其分发给各个工作人员以施加这些限制。我给你的链接中有一些例子可以帮助你到达那里。然而,在没有这些工具的帮助下纯粹用 PHP 来做这件事将被证明是相当棘手的,如果不仔细设计和考虑,可能会导致一些非常极端的错误行为。

于 2012-12-10T23:56:33.280 回答
1

某些 API 在响应标头中返回速率限制信息。查看: HTTP API 速率限制示例 HTTP 响应标头 此信息将帮助您等待几纳秒,然后再继续使用 PHP 的下一个请求time_nanosleep()

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

X-RateLimit-Remaining现在,当涉及到限制一些在其返回标头中没有类似内容的 URL 请求时,我发现这有点矫枉过正。API 请求通常很慢。所以我在下面构建了 PHP 脚本。

这个 PHP 脚本将只等待几毫秒,基于$throttlerID. 更高requestsInSeconds将导致更短的等待时间...如果$throttlerID在同时请求中使用相同的请求,则每个请求将使用 File-Locking ( ) 等待另一个请求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。而已!

于 2021-05-11T19:39:12.270 回答