PHP cURL multi_exec 请求之间的延迟

6
如果我运行标准的cURL_multi_exec函数(如下例),我会立即得到所有请求的cURL句柄。我想在每个请求之间加上100毫秒的延迟,有办法吗?(在Google和StackOverflow搜索中找不到任何信息)我尝试在curl_multi_exec()之前使用usleep()来减慢脚本的速度,但它并不能推迟每个请求。
// array of curl handles & results
$curlies = array();
$result = array();
$mh = curl_multi_init();

// setup curl requests
for ($id = 0; $id <= 10; $id += 1) {
    $curlies[$id] = curl_init();
    curl_setopt($curlies[$id], CURLOPT_URL,            "http://google.com");
    curl_setopt($curlies[$id], CURLOPT_HEADER,         0);
    curl_setopt($curlies[$id], CURLOPT_RETURNTRANSFER, 1);
    curl_multi_add_handle($mh, $curlies[$id]);
}

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

// get content and remove handles
foreach($curlies as $id => $c) {
    $result[$id] = curl_multi_getcontent($c);
    curl_multi_remove_handle($mh, $c);
}

// all done
curl_multi_close($mh);

我一整天都在处理这个问题,任何帮助都将不胜感激!谢谢。

编辑:还有其他非cUrl方法吗?那也能回答我的问题。


不,PHP的curl支持不提供那种功能。 - Marc B
PHP根本不支持多线程。您需要并行运行多个脚本副本。每个脚本副本都是完全独立的。您需要一些方法来告诉每个脚本应该获取哪些URL。 - Marc B
我了解cURL multi只有一个线程在等待所有连接被解决。类似的单线程解决方案将会解决我的问题。我不想使用1000次请求同时攻击任何服务器,但也不想一个一个地运行请求(太慢了)。 - Edi Budimilic
1
所有的URL是否在一个站点上?还是你正在访问多个站点?如果是多个站点,请在每个多线程中访问一个站点,并在整个脚本上暂停100毫秒。这会使每个站点看起来像是每100毫秒一次请求,尽管你同时正在访问5或10个站点。 - Marc B
@Marc B 所有的 URL 都在同一个网站上。我正在不同服务器上 ping 我自己的 API。 - Edi Budimilic
显示剩余2条评论
4个回答

4
是的,这是可能的。如果您使用ParallelCurl库,您可以更容易地添加100毫秒延迟,使用usleep(),因为您可以将单独的请求添加到下载队列中。
for ($urls as $url) {
    $pcurl->startRequest($url);
    usleep(100000);
}

很遗憾,它不起作用。脚本永远挂起,我不是唯一报告这个问题的人:https://github.com/petewarden/ParallelCurl/issues - Edi Budimilic
1
奇怪。也许自从我上次获取它以来已经更新了。我现在正在两个不同的应用程序中使用这种方法,没有问题。今晚我会查看我的版本并发布更新。也许这与我所做的不同修改有关... - Brad
我确认。这种方法一点问题都没有。+1。在Web上无法使用Forking。但是ParallelCurl可以在Web和命令行上工作。 - asiby

3

不要认为你不能做到。如果你从命令行运行这个脚本,你可以将它 分叉成10个进程,然后从每个进程中发出常规的curl请求。这将允许你对时间进行精细控制。


它使用这个脚本成功运行:http://blog.motane.lu/2009/01/02/multithreading-in-php/ - Edi Budimilic

1

PHP并不是解决这个问题的方案。复制脚本也没有帮助。在开始时或许可以,但一旦你需要获取更多的网站,你会发现你的服务器非常非常繁忙,无论是成本还是脚本稳定性,你都应该重新考虑使用其他的想法。

你可以轻松地使用Python来完成这个任务,对于非阻塞实时调用API端点,你应该使用Socket.IO + Node.JS或者只是Node.JS,或者...哈哈

如果你没有时间或者意愿,你可以使用这样的东西:

http://framework.zend.com/manual/en/zendx.console.process.unix.overview.html

实际上这完全取决于你想要实现什么。


我同意最后一句话 :) 我一直在ping同一个服务器(API)。服务器可以保留请求,但我只想将它们延迟而不必等待上一个请求完成。 - Edi Budimilic

0
你可以尝试这个方法:
在数据库中存储一个时间戳,添加一个句柄并调用curl_multi_exec
使用CURLOPT_PROGRESSFUNCTION检查时间并在需要时添加更多句柄。
这里 cURL和libcurl的作者Daniel Stenberg表示,在执行curl_multi_exec后添加更多句柄是可能的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接