【问题标题】:cURL Multi Threading with PHP使用 PHP 的 cURL 多线程
【发布时间】:2012-09-05 19:39:06
【问题描述】:

我正在使用 cURL 来获取存储在数据库中的 20,000 多个域名的排名数据。

我使用的代码是http://semlabs.co.uk/journal/object-oriented-curl-class-with-multi-threading

数组 $competeRequests 是 20,000 个对网站排名的competition.com api 的请求。

这是一个示例请求: http://apps.compete.com/sites/stackoverflow.com/trended/rank/?apikey=xxxx&start_date=201207&end_date=201208&jsonp=";

由于有 20,000 个这样的请求,我想将它们分成块,所以我使用以下代码来完成:

foreach(array_chunk($competeRequests, 1000) as $requests) {
    foreach($requests as $request) {
        $curl->addSession( $request, $opts );
    }

}

这非常适合批量发送 1,000 个请求,但脚本执行时间过长。我已将 max_execution_time 增加到 10 分钟以上。

有没有办法从我的数组发送 1000 个请求,然后解析结果,然后输出状态更新,然后继续下一个 1000 个请求,直到数组为空?截至目前,在脚本执行的整个过程中屏幕一直保持白色,可能超过 10 分钟。

【问题讨论】:

  • 你必须通过你的服务器运行这个脚本,你不能手动运行它吗? ... 20,000 个请求是很多请求,这很可能必须在后台运行
  • 我确实想最终将它作为 cron 作业运行..现在我正在浏览器中执行它..
  • 我已经在使用 curl multi... "我使用的代码是 semlabs.co.uk/journal/…。"

标签: php curl nginx


【解决方案1】:

以上接受的答案已经过时,所以,正确的答案必须被投票。

http://php.net/manual/en/function.curl-multi-init.php

现在,PHP 支持同时获取多个 URL。

【讨论】:

  • 正确答案是我当时给出的那个。没有必要为了跟上科学和发展的步伐而纠正关于 SO 的老问题。在当时,这就是答案。你不知道是否有人使用旧的 PHP 版本,有可能他们是。不要假设每个人都运行最新的。如果您声称 PHP 中存在某种支持,您还应该提及您正在谈论的版本。
【解决方案2】:

这个总是为我做这项工作...https://github.com/petewarden/ParallelCurl

【讨论】:

【解决方案3】:

https://github.com/krakjoe/pthreads

您可以使用 PHP 线程,所描述的代码只是可怕的线程编程,我不建议您这样做,但想向您展示 20,000 个线程的开销......这是 18 秒,在我的当前硬件是 Intel G620(双核),具有 8gigs 内存,在服务器硬件上,您可以期待更快的结果......如何处理这样的任务取决于您的资源以及您请求的服务的资源。 ..

【讨论】:

  • “编程”本身很好——它完全没有线程调度/线程执行队列,这使得这个脚本效率低下。一般来说,一个好的调度器不应该允许超过insert amount of CPU cores here同时运行,除了具有HT的机器和具有极端wait时间的线程并且它应该能够排队至少2^ 32 线程
【解决方案4】:

把它放在你的 php 脚本的顶部:

set_time_limit(0);
@apache_setenv('no-gzip', 1);//comment this out if you use nginx instead of apache
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);

这将禁用 Web 服务器或 php 可能正在执行的所有缓存,使您的输出在脚本运行时显示在浏览器上。

如果你使用 nginx 网络服务器而不是 apache,请注意注释掉 apache_setenv 这一行。

nginx 更新:

所以 OP 使用的是 nginx,这让事情变得有点棘手,因为 nginx 不允许从 PHP 禁用 gzip 压缩。我也使用 nginx,但我发现它默认处于活动状态,请参阅:

cat /etc/nginx/nginx.conf | grep gzip
    gzip on;
    gzip_disable "msie6";
    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

所以你需要在 nginx.conf 上禁用 gzip 并重新启动 nginx:

/etc/init.d/nginx restart

或者您可以使用gzip_disablegzip_types 选项,分别针对某些浏览器或某些页面内容类型有条件地禁用gzip。

【讨论】:

  • 注释掉了那一行。现在正在尝试,但它似乎仍然没有输出任何结果,直到脚本完成执行每个所有域而不是每个批次
  • 是的,只是确认它在脚本完成所有 20,000 之后直到最后才输出任何内容
  • 您对更高效的处理有什么想法吗?基本上我的数据库有 20,000 个域,并使用他们的 api 查询competition.com 来获取排名,然后将排名写入数据库。最终我想安排脚本每个月自动运行,所以我希望避免 JavaScript 或任何其他客户端脚本。
  • 查看我上面的 nginx 更新,看看禁用 gzip 是否适合您的情况。
  • 对任何人来说,我们需要从 js 进行 ajax 调用来解决这个问题^ 禁用缓存是个坏主意,比如说有人打开了几千个 http 请求,服务器就会崩溃,就像他一样将交换到极限。
猜你喜欢
  • 2020-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-11
  • 1970-01-01
  • 2020-08-11
  • 1970-01-01
相关资源
最近更新 更多