让curl_multi'睡觉'或者在发送下一个请求之前等待

时间:2016-01-06 20:57:31

标签: php curl asynchronous

我使用curl_multi发出异步请求:http://php.net/manual/en/function.curl-multi-init.php

脚本向所有给定的URL发送请求,这对于我正在做的事情来说有点快。有没有办法减慢请求率?

2 个答案:

答案 0 :(得分:3)

我前段时间做过这个,但我现在找不到代码。

但基本上你不能停止curl_multi_exec()循环,所以我将该处理包装在另一个循环中,只需要它就可以使用2个卷曲句柄和2000个URL来处理。

完成后,然后设置接下来的20个网址,让它处理并再次运行curl_multi_exec()功能,但你可以将睡眠置于此循环中

我知道有点模糊,但希望它会给你一个10的启动器

我通过更改define可以配置卷曲句柄的数量,并且可以以相同的方式配置传递到curl_multi_exec()循环的URL的数量,这使得将处理调整为非常容易适合这种情况。

答案 1 :(得分:3)

function asyncCurl($url){
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
  curl_setopt($ch, CURLOPT_TIMEOUT, 1);
  curl_exec($ch);
  curl_close($ch);
}

$timeout = 3; // in seconds
$urls = array(...);

foreach($urls as $url){
  asyncCurl($url);
  sleep($timeout);
}

如果您需要获得响应,仍然可以通过创建"后台进程"服务器上的东西类型。这将需要2个脚本而不是一个。

<强> background.php

function curl($url){
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, $url);
  $a = curl_exec($ch);
  curl_close($ch);
  return $a;
}

$response = curl($_GET['url']);

// code here to handle the response

doRequest.php (或者其他,这是您将在浏览器中调用的那个)

function asyncCurl($url){
  $ch = curl_init();
  curl_setopt($ch, CURLOPT_URL, "mydomain.com/background.php?url=".urlencode($url));
  curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
  curl_setopt($ch, CURLOPT_TIMEOUT, 1);
  curl_exec($ch);
  curl_close($ch);
}

$timeout = 3; // in seconds
$urls = array(...);

foreach($urls as $url){
  asyncCurl($url);
  sleep($timeout);
}

这里的想法是PHP是单线程的,但没有理由你不能同时运行多个PHP进程。唯一的缺点是你必须在一个脚本上发出请求并在另一个脚本上处理响应。

选项3:在输出可用后立即显示。

这个方法与上面的方法完全相同,只是它使用javascript来创建一个新的php进程。你没有标记javascript,但这是实现两者的唯一方法

  • 带有超时的异步请求

  • 一旦可用,就会显示回复

    <强> doRequest.php

    <?php
    
    $urls = array(); // fill with your urls
    $timeout = 3; // in seconds
    
    if (isset($_GET['url'])) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $_GET['url']);
        $a = curl_exec($ch);
        curl_close($ch);
        echo $a;
        exit;
    }
    
    ?><html>
    <body>
        <div id='results'></div>
        <script>
    
            var urls = <?php echo json_encode($urls); ?>;
            var currentIndex = 0;
    
            function doRequest(url) {
                var xhttp = new XMLHttpRequest();
                xhttp.onreadystatechange = function () {
                    if (xhttp.readyState == 4 && xhttp.status == 200) {
                        document.getElementById("results").insertAdjacentHTML("beforeend", "<hr>" + xhttp.responseText);
                    }
                };
                xhttp.open("GET", "doRequest.php?url=" + encodeURIComponent(url), true);
                xhttp.send();
            }
    
            var index=0;
            function startLoop(){
                var url = urls[index];
                doRequest(url);
                setTimeout(function(){
                    index++;
                    if('undefined' != urls[index]) startLoop();
                }, <?php echo $timeout*1000; ?>);
            }
    
            startLoop();
        </script>
    </body>
    

发生了什么?服务器正在为每个网址创建一个新请求,然后使用普通卷曲来获取响应,但是我们使用ajax本质上是异步的,而不是使用curl来创建新进程。能够创建多个PHP进程并等待响应。

一帆风顺!