【问题标题】:Rate limit outgoing PHP+curl requests速率限制传出 PHP+curl 请求
【发布时间】:2012-09-03 17:10:27
【问题描述】:

有没有办法限制(有延迟)向外部服务器传出的 PHP+curl 请求,以便每秒只有 n 个请求? PHP 在 Fastcgi 模式下使用,因此无法使用睡眠。

【问题讨论】:

  • PHP脚本是如何执行的?每个浏览器或 cron/schedule?
  • 每个浏览器有多个 PHP Fastcgi 进程。不幸的是,nginx 似乎没有全局速率限制。

标签: php api curl limit


【解决方案1】:

您可以使用token bucket algorithm 控制速率。当您想控制一个资源的所有 PHP 进程的速率时,您需要共享存储桶的状态。您可以使用我的实现以线程安全的方式执行此操作:bandwidth-throttle/token-bucket

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

$storage  = new FileStorage(__DIR__ . "/api.bucket");
$rate     = new Rate(10, Rate::SECOND);
$bucket   = new TokenBucket(10, $rate, $storage);
$consumer = new BlockingConsumer($bucket);
$bucket->bootstrap(10);

// This blocks all processes to the rate of 10 requests/second
$consumer->consume(1);

$api->doSomething();

【讨论】:

  • Laravel 从 5.2 开始添加了一个中间件来限制每 N 分钟的调用次数。这虽然涵盖了我每月的存储桶大小分配问题。不错的图书馆。
【解决方案2】:

是的。有 curl 多处理程序...

(您可以使用 this library 以 OOP 方式进行操作)

例如:

    // Creates the curl multi handle
    $mh = curl_multi_init();
    $handles = array();

    foreach($urls as $url)
    {
        // Create a new single curl handle
        $ch = curl_init();

        // Set options
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 300);

        // Add to the multi handle
        curl_multi_add_handle($mh,$ch);

        // Put the handles in an array to loop this later on
        $handles[] = $ch;
    }

    // Execute the multi handle
    $running=null;

    do
    {
        $mrc = curl_multi_exec($mh,$running);

        // Added a usleep for 0.50 seconds to reduce load
        usleep (250000);
    }
    while($running > 0);

    // Get the content of the urls (if there is any)
    $output = array();
    for($i=0; $i<count($handles); $i++)
    {
        // Get the content of the handle
        $content = curl_multi_getcontent($handles[$i]);
        $output[] = $content;

        if($printOutput) {
            echo $content;
        }

        // Remove the handle from the multi handle
        curl_multi_remove_handle($mh,$handles[$i]);
    }

    // close the multi curl handle to free system resources
    curl_multi_close($mh);

【讨论】:

  • 这行不通,因为PHP是Fastcgi模式,所以有多个PHP进程。不确定上述是否可以阻止 PHP 进程的多个传出连接。
  • @vamur 试试链接的要点。
  • @vimur 链接的要点不再存在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-31
  • 1970-01-01
  • 2018-11-05
  • 2013-12-13
  • 1970-01-01
  • 2019-01-14
相关资源
最近更新 更多