使curl_multi';睡眠';或者在发送下一个请求之前等待


Make curl_multi 'sleep' or wait before sending next request

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

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

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);
}

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

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>
    

现在的情况是,服务器为每个url创建一个新的请求,然后使用普通的curl来获得响应,但我们没有使用curl来创建新的进程,而是使用ajax,它本质上是异步的,能够创建多个PHP进程并等待响应。

上帝保佑!

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

但基本上,您无法停止curl_multi_exec()循环,因此我将处理过程封装在另一个循环中,该循环只给了它2个要使用的curl句柄和2000个url中的20个要处理。

一旦完成,您就可以设置接下来的20个url,让它处理并再次运行curl_multi_exec()函数,但您可以将睡眠放在这个循环中

我知道有点模糊,但希望它能给你一个10 的首发

我通过更改define和传递到curl_multi_exec()循环中的url的数量来配置curl句柄的数量,这使得调整处理以适应这种情况变得非常容易。