Php 使卷曲多';睡眠';或者在发送下一个请求之前等待

Php 使卷曲多';睡眠';或者在发送下一个请求之前等待,php,curl,asynchronous,Php,Curl,Asynchronous,我使用curl\u multi发出异步请求: 脚本将请求发送到所有给定的URL,这对于我正在做的事情来说有点太快了。有没有办法降低请求速率 我以前做过,但现在找不到代码 但是基本上你不能停止curl\u multi\u exec()循环,所以我把这个过程包装在另一个循环中,让它使用2个curl句柄,处理2000个URL中的20个 完成后,您将为它设置接下来的20个URL以进行处理,并再次运行curl\u multi\u exec()函数,但您可以将睡眠放在这个循环中 我知道有点含糊,但希望它能给

我使用curl\u multi发出异步请求:


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

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

但是基本上你不能停止
curl\u multi\u exec()
循环,所以我把这个过程包装在另一个循环中,让它使用2个curl句柄,处理2000个URL中的20个

完成后,您将为它设置接下来的20个URL以进行处理,并再次运行
curl\u multi\u exec()
函数,但您可以将睡眠放在这个循环中

我知道有点含糊,但希望它能给你10分钟的首发机会

我通过更改
define
和传递到
curl\u multi\u exec()
循环中的URL数量,以同样的方式配置了curl句柄的数量,这使得调整处理过程以适应这种情况变得非常容易

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
<?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>
doRequest.php(或者其他,这是您将在浏览器中调用的)

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


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

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

  • 带超时的异步请求

  • 一旦响应可用,立即显示响应

    doRequest.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
    
    <?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>
    
    
    var url=;
    var currentIndex=0;
    函数doRequest(url){
    var xhttp=newXMLHttpRequest();
    xhttp.onreadystatechange=函数(){
    如果(xhttp.readyState==4&&xhttp.status==200){
    document.getElementById(“结果”).insertAdjacentHTML(“beforeed”,“
    ”+xhttp.responseText); } }; open(“GET”、“doRequest.php?url=“+encodeURIComponent(url),true); xhttp.send(); } var指数=0; 函数startoop(){ var url=url[索引]; doRequest(url); setTimeout(函数(){ 索引++; if('undefined'!=url[index])startoop(); }, ); } startoop();

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


祝你好运

一次卷曲一个太慢了吗@MonkeyZeus是的,太慢了。我想通过增加一些时间间隔来进行更多的控制,我强烈建议您更新更详细的问题。我将包括一个虚假的URL列表,并解释在什么情况下需要在另一个URL之后触发特定的URL。我打算建议您对一些请求进行多重卷积,并对“时间敏感”的请求进行常规卷积。目前看来,这可能是唯一可以帮助您实现目标的方法,但它的文档严重缺乏。您还可以研究如何划分流程,并为每个分支分配一个专用的URL+睡眠时间。这里建议使用分叉:感谢您的努力,但我希望每个URL请求之间有一个时间间隔。我不想同时发送两个或更多的请求,我更希望中间有半秒。事实上,我很惊讶没有curl函数来处理这个问题。curl\u multi\u exec()的基本前提是“开火并忘记”,我假设你访问的是同一个网站,有很多请求。是的,同一个网站,每次都被禁止:)我也不喜欢打击任何人的想法server@Youss你当然应该在你的问题中添加这个小细节:“是的,是同一个网站,每次都被禁止”谢谢,但是如果一个网站需要20秒的时间来回复,我必须等20秒。这就是我使用multi_curl的原因,所以我不必等着注意我是如何在函数标题中添加“async”的。它是异步的。它不会等待。换句话说,它发出请求,然后立即关闭连接,以便服务器可以执行任何操作。。然后它休眠,然后请求另一个。这假设您不需要请求的响应。。如果你这样做了,还有一件事你可以做,让我知道。实际上我确实需要回复(全部内容)。我还能试什么?