2011-06-14 134 views
0

我正在使用当前代码尝试使用cURL异步执行两个脚本。每个脚本都托管在不同的域上,需要大约30秒才能完成。我希望这些在后台运行,以便页面可以继续加载,但它会一直挂起直到完成。我在考虑cURL的工作原理时完全错了吗?或者我做错了什么?cURL导致页面挂起

UPDATE:

$.ajax({ 
    type : 'POST', 
    url  : 'ajax.php?mode=process', 
    data : '$url', 
    complete: function(data) 
    { 
     $('#test'+num).append('Operation successful.'); 
    } 
}); 

货号是div的ID。它们是通过代码生成的。所有这些都正常工作,除了cURL锁定服务器,直到完成处理文件。

下面的代码现在在另一个页面上,专门用于处理从上面的jQuery ajax调用传入的URL。

$cURLs = array(
    "script_url?param1=1&param2=2", 
    "script_url?param1=5&param2=6"); 
$result = array(); 
$mh = curl_multi_init(); 

foreach ($data as $id => $d) 
{ 
    $cURLs[$id] = curl_init(); 
    $url = (is_array($d) && !empty($d['url'])) ? $d['url'] : $d; 
    curl_setopt($cURLs[$id], CURLOPT_URL,   $url); 
    curl_setopt($cURLs[$id], CURLOPT_HEADER,   0); 
    curl_setopt($cURLs[$id], CURLOPT_RETURNTRANSFER, 1); 

    if (is_array($d)) 
    { 
      if (!empty($d['post'])) 
      { 
        curl_setopt($cURLs[$id], CURLOPT_POST,  1); 
        curl_setopt($cURLs[$id], CURLOPT_POSTFIELDS, $d['post']); 
      } 
    } 

    if (!empty($options)) 
      curl_setopt_array($cURLs[$id], $options); 

    curl_multi_add_handle($mh, $cURLs[$id]); 
} 

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

foreach($cURLs as $id => $c) 
{ 
    $result[$id] = curl_multi_getcontent($c); 
    curl_multi_remove_handle($mh, $c); 
} 

curl_multi_close($mh); 
echo "<pre>" . print_r($result, 1) . "</pre>"; 
+2

调用卷曲就像调用任何其它功能 - 脚本块,直到函数返回。大多数功能几乎是瞬时的,所以你不会注意到。 curl完全依赖于远程资源的作用(以及它自己的超时参数)。 – 2011-06-14 16:29:59

回答

3

不幸的是,你的页面将不会完成加载,直到你的脚本完成执行。即使您使用cURL Multi功能,也只能在脚本运行时使用。

如果您需要在后台运行脚本,则必须找到其他方法,例如在数据库中排队下载作业,并且运行脚本以逐个检查该队列。

+0

考虑编写一个PHP守护进程/任务或cron脚本来扫描队列表以查找要下载的文件,并设计您的A.php页面以扫描保存在表中的结果。如果需要,脚本B.php可能会每分钟检查一次表格。但是,您可能需要运行许多B.php任务,因为每个B.php任务都无法同时为多个用户提供服务。 – 2011-06-14 17:21:32

+0

@memnoch_proxy我现在正在做这件事。将初始脚本加载所有变量并将它们保存在我的数据库中,然后通过Ajax调用脚本。脚本将遍历表中的每一行,处理它们并将其删除。同时,我要在主页上运行一个小型JS来每隔几秒查询一次数据库以查看表是否消失。当它发生时,那个缺失的表格将会完成报告。对此有何想法? – Nathan 2011-06-14 17:24:35

+0

听起来像一个好开始 – 2011-06-14 17:29:10

0

如果您希望异步做到这一点,你需要完成输出到你的页面,然后使用jQuery来调用,使用卷曲加载数据的脚本。

+3

为什么选jQuery?为什么没有图书馆?只有jQuery做ajax - 非常不真实。 – Neal 2011-06-14 16:30:54

+0

你有没有做过这种方法?使用jQuery来运行cURL请求并使其异步执行? – Nathan 2011-06-14 16:31:03

+2

@Andrew,他暗示你有一个脚本来完成它现在所做的事情,但是客户端页面加载,然后用jQuery调用这个脚本。这将为你工作,取决于你的需求。请记住,如果客户端关闭连接,PHP将被终止,除非您在php.ini中另外配置它​​。 – Brad 2011-06-14 16:39:53

1

将此用作卷曲请求的选项。

$CURL_OPTS = array(
    CURLOPT_CONNECTTIMEOUT => 10, 
    CURLOPT_RETURNTRANSFER => true, 
    CURLOPT_TIMEOUT  => 60, 
); 
+0

这不是真正的问题在这里。脚本本身需要大约30秒才能完成,我称它为71次,如果同步完成,则需要大约35分钟才能完成。它似乎一次只能处理大约6-8个文件,将其总处理时间缩短到5分钟左右。但是,在此期间服务器无法访问。在处理时,不能加载其他页面。我**需要**它是一个后台进程,这是我_thought_ cURL会为我做的。 – Nathan 2011-06-14 17:13:00

+0

这是设置超时但没有达到任何并行性的示例。 – 2011-06-14 17:18:39

+0

我认为你需要cron作业而不是 – 2011-06-22 17:40:16

0

我知道这是一个老帖子...但我也有类似的问题,我能避开它...不知道如果这是你的一样,因为你只共享的一部分你的代码,但我会分享这个,因为我发现很难找到正确的答案,这听起来非常像我试图解决:

我有一个ajax调用,它叫a.php,a .php通过cURL CLI调用b.php来在后台处理页面(使用PHP的exec()函数)b.php使用libcurl来刮取网站... b.php导致a.php停止响应我的ajax请求检查刮刀的状态。我发现原因是因为我将刮板信息存储到全局的$ _SESSION var中......您无法在多个位置读取/写入同一个会话,所以我周期性的ajax请求到a.php(这是使用与b.php上的cURL刮板相同的会话)被挂起。定期在整个cURL刮取器中使用session_write_close()会导致我的ajax请求不会挂起,因为会话不再阻止页面请求通过。

我很想找到了,如果这是你的挂Ajax请求的原因,直到完成卷曲处理