【问题标题】:Multi-threaded Curl Can't Handle Large Number of Concurrent URLs?多线程 Curl 无法处理大量并发 URL?
【发布时间】:2016-02-21 21:27:15
【问题描述】:

我必须同时调用大量 API。我正在尝试通过多线程 curl 来执行此操作,但如果我传递了很多 URL,它似乎无法正确获取所有 API 结果(一些错误;我认为它超时了???) .一次 50 个 URL 似乎是我可以通过的最大值,而一次大约 100 个是我真正开始看到问题的时候。正因为如此,我不得不实现逻辑来分块我尝试在给定时间卷曲的 URL。

问题:

  1. 什么可能导致我的卷曲问题?
  2. 我可以设置 curl 中的某些内容来告诉它等待更长时间以等待响应 - 以防我的问题与超时有关?
  3. 我的服务器/php.ini 中有什么可以配置来提高我的脚本的性能吗?

这是脚本:

function multithreaded_curl(array $urls, $concurrent_urls = 50)
    {
        // Data to be returned
        $total_results = array();

        // Chunk the URLs
        $chunked_urls = array_chunk($urls, $concurrent_urls);
        foreach ($chunked_urls as $chunked_url) {
            // Chunked results
            $results = array();

            // Array of cURL handles
            $curl_handles = array();

            // Multi-handle
            $mh = curl_multi_init();

            // Loop through $chunked_urls and create curl handles, then add them to the multi-handle
            foreach ($chunked_url as $k => $v) {
                $curl_handles[$k] = curl_init();

                curl_setopt($curl_handles[$k], CURLOPT_URL, $v);
                curl_setopt($curl_handles[$k], CURLOPT_HEADER, 0);
                curl_setopt($curl_handles[$k], CURLOPT_RETURNTRANSFER, 1);
                curl_setopt($curl_handles[$k], CURLOPT_SSL_VERIFYPEER, 0);

                curl_multi_add_handle($mh, $curl_handles[$k]);
            }

            // Execute the handles
            $running = NULL;
            do {
                curl_multi_exec($mh, $running);
            } while ($running > 0);

            // Get content and remove handles
            foreach ($curl_handles as $k => $v) {
                $results[$k] = json_decode(curl_multi_getcontent($v), TRUE);
                curl_multi_remove_handle($mh, $v);
            }

            // All done
            curl_multi_close($mh);

            // Combine results
            $total_results = array_merge($total_results, $results);
        }

        return $total_results;
    }

【问题讨论】:

  • 1 - 它不是多线程 2 - 它可能是您达到的 PHP 超时,而不是实际的 curl 限制
  • 1. curl_multi_exec 不是多线程的吗? 2.我在调用这个函数之前已经执行了set_time_limit(0);
  • Golang 在这里会很有帮助:D 容易并发。
  • 可能发生了很多事情。在失败的句柄上调用curl_getinfo()curl_error() 以获取更多详细信息。没有看到我们甚至不知道为什么它真的失败了。除此之外,您可能会受到速率限制,某些服务器可能会阻止来自单个 IP 的超过 x 的同时连接,您的操作系统可能会遇到套接字或描述符耗尽的问题。如果您针对 API 请求访问许多相同的主机,那么在服务器支持的情况下,重新使用相同的 cURL 句柄来利用保持活动连接会更有效。
  • 就用这个库吧,github.com/marcushat/RollingCurlX

标签: php multithreading curl


【解决方案1】:

关于 Q1:如前所述,有几个选项可以解决该算法的问题。首先是它可能会耗尽本地(句柄等)以及远程(maxConnections、maxThreads 等)资源。不要那样做。

关于 Q2:您不需要(见下文),但请在猜测错误之前获取错误响应。

关于 Q3:是的,REMOTE 网络服务器有几个选项,具体取决于远程网络服务器的供应商(线程数限制、最大连接数、每个客户端的最大连接数等)。如果这也是您的服务器,您可以调整这些以更好地满足您的需求,但首先您应该调整客户端算法。

总体而言,一次启动多个连接并没有多大意义。连接重用速度要快得多,并且不会破坏您的本地句柄等,并且不会对远程系统进行 DOS 攻击。这样做的唯一原因是服务器处理请求的时间比 io 需要的时间长。

当您只是假设一次 4 个连接并重复使用它们而不是创建新连接时,您是否检查过速度?实际上,您正在填充 curl_handles[] 以供每次使用。创建 IO 对象需要时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 1970-01-01
    相关资源
    最近更新 更多