PHP-使用multi_curl进行并行处理是一个好主意吗?
我需要在PHP中进行并行处理,但是如果不安装扩展,PHP就不支持并行处理,所以我使用PHP-使用multi_curl进行并行处理是一个好主意吗?,php,multithreading,curl,parallel-processing,Php,Multithreading,Curl,Parallel Processing,我需要在PHP中进行并行处理,但是如果不安装扩展,PHP就不支持并行处理,所以我使用multi_curl来实现这一点 main.php-构建一个URL数组,这些URL都是process.php,具有不同的$\u GET参数。然后使用multi_curl执行它们 process.php-每个线程的处理逻辑 我只是想知道这是否是一种可行的做事方式。这是弱智吗?这会造成很多开销吗?有没有更明智的方法?谢谢。当然,一般来说,这是一种可行的方式,这就是功能存在的原因 和往常一样,细节才是魔鬼。多个并发请求
multi_curl
来实现这一点
main.php
-构建一个URL数组,这些URL都是process.php
,具有不同的$\u GET参数。然后使用multi_curl执行它们
process.php
-每个线程的处理逻辑
我只是想知道这是否是一种可行的做事方式。这是弱智吗?这会造成很多开销吗?有没有更明智的方法?谢谢。当然,一般来说,这是一种可行的方式,这就是功能存在的原因
和往常一样,细节才是魔鬼。多个并发请求将与其他进程竞争并消耗服务器资源;您需要调节并发度。请记住,PHP不支持通过任何合理的方式进行多处理,对于您的情况,multi_curl似乎是一个很好的解决方案 PHP线程 享受 要在unix中安装,您需要一个线程安全版本的PHP。大多数发行版不打包此版本,因此您必须自己构建它 关于如何做到这一点的简要说明如下:
cd /usr/src
wget http://php.net/get/php-5.3.17.tar.bz2/from/us.php.net/mirror
tar -xf php-5.3.17.tar.bz2
cd php-5.3.17/ext
wget https://github.com/krakjoe/pthreads/tarball/master -O pthreads.tar.gz
tar -xf pthreads.tar.gz
mv krakjoe-pthreads* pthreads
cd ../
./buildconf --force
./configure --enable-maintainer-zts --enable-pthreads --prefix=/usr
make
make install
首先,我要构建一个独立的副本--前缀有一个私有位置,比如--prefix=/home/mydir,或者一些发行版有一个/usr/src/debug,这是一个很好的地方。很明显,您需要添加——使用mysql等,但如何添加取决于您的系统(提示,您可以使用php-i | grep configure>factory.config来保存当前的php安装配置行,并在您的自定义构建基础上,知道它抱怨的任何库都不可用,这是一个很好的| yum install away) 如果您在Web服务器上运行PHP(可能无法使用multi_curl),使其并行运行脚本的一种方法(没有库)是打开localhost:80的套接字并手动使Web服务器运行所需的脚本。它们将使用服务器多线程并行运行。然后在一个循环中收集所有结果,当所有结果都完成时(或在您选择的超时之后),继续 这是一段取自脚本的代码,该脚本检索网页上引用的所有图像的大小 get_img_size.php脚本检索一个图像的大小和信息 $sockets[]是一个数组,它为每个要测试的映像保留一个套接字
foreach($metaItems['items'] as $uCnt=>$uVal) {
$metaItem=ContentLoader::splitOneNew($metaItems,$uCnt);
$AnImage=$metaItem['url'];
$sockets[$AnImage] = fsockopen($_SERVER['HTTP_HOST'], 80, $errno, $errstr, 30);
if(!$sockets[$AnImage]) {
echo "$errstr ($errno)<br />\n";
} else {
$pathToRetriever=dirname($_SERVER['PHP_SELF']).'/tools/get_img_size.php?url='.rawurlencode($AnImage);
// echo('<div>META Retrieving '.$pathToRetriever.' on server '.$_SERVER['HTTP_HOST'].'</div>');
$out = "GET $pathToRetriever HTTP/1.1\r\n";
$out .= "Host: ".$_SERVER['HTTP_HOST']."\r\n";
$out .= "Connection: Close\r\n\r\n";
// echo($out);
fwrite($sockets[$AnImage], $out);
fflush($sockets[$AnImage]);
// echo("<div>Socket open for $AnImage...</div>");
// flush();
}
}
} else $FoundImagePaths2[]=$metaItems; // ALL of them urls belongs to us
foreach($metaItems['items']作为$uCnt=>$uVal){
$metaItem=ContentLoader::splitOneNew($metaItems,$uCnt);
$AnImage=$metaItem['url'];
$sockets[$AnImage]=fsockopen($\服务器['HTTP\主机'],80,$errno,$errstr,30);
如果(!$sockets[$AnImage]){
回显“$errstr($errno)
\n”;
}否则{
$pathToRetriever=dirname($\u SERVER['PHP\u SELF'])。/tools/get\u img\u size.PHP?url='.rawurlencode($AnImage);
//echo('META-Retrieving'.$pathToRetriever.'在服务器'.$'上'.$'服务器['HTTP\u主机'.');
$out=“GET$pathToRetriever HTTP/1.1\r\n”;
$out.=“主机:”.$\u服务器['HTTP\U主机]。“\r\n”;
$out.=“连接:关闭\r\n\r\n”;
//echo($out);
fwrite($sockets[$AnImage],$out);
fflush($sockets[$AnImage]);
//echo(“为$AnImage打开的插座…”);
//冲洗();
}
}
}else$FoundImagePaths2[]=$metaItems;//所有这些URL都属于我们
在此之后,您可以在“线程”继续工作的同时完成自己的业务,然后,在一个循环中,继续读取所有$sockets[]并测试EOF。在本例中,代码后面的很多部分(每个$AnImage都有一个循环):
if(isset($sockets[$AnImage])){
if(feof($sockets[$AnImage])){
如果(!isset($sizes[$AnImage]))$sizes[$AnImage]='';
$size[$AnImage]。=fgets($sockets[$AnImage],4096);
//echo(“HTML$AnImage DONE.”);
//回声(“[”$size[$AnImage]。“]”);
//冲洗();
fclose($sockets[$AnImage]);
未设置($sockets[$AnImage]);
$mysizes=ContentLoader::cleanResponse($sizes[$AnImage]);
//回声($size[$AnImage]);
//echo(ContentLoader::cleanResponse($size[$AnImage]);
如果(!is_数组($mysizes)){continue;}
如果($mysizes[0]>64&&$mysizes[1]>64&($mysizes[0]>128 | |$mysizes[1]>128))
$FoundImagePaths2[]=array('kind'=>'image','url'=>$AnImage,'ext'=>$ext,'width'=>$mysizes[0],'height'=>$mysizes[1],'mime'=>$mysizes['mime']);
它在内存、进程和速度方面都不高效,但如果一个图像只需要几秒钟,那么整个包含20多个图像的页面都需要同样的几秒钟来测试它们。毕竟,它是某种并行PHP。听说过吗?@Orbling这是我指的扩展。但我不想安装额外的,而且我还没有安装rd非常好。在大多数系统上,分叉是多进程执行的基础。只是人们不经常在PHP中使用它,部分原因是PHP程序员不习惯这个概念和注意事项。有很多gotchas使用PHP来做这件事,但经过仔细处理,它是一种标准的、合理的分割进程的方法sing curl在大多数情况下都有很高的开销,但它的优点是通过您的Web服务器,因此可以在机器上实现负载平衡,等等。PHP并没有很好地针对并发性和并行处理进行定制。如果您正在生成内部请求,那么最好将工作交给Erlang。除非存在较大的b无法快速移植的库代码体。+1听起来是处理t的一个非常好的方法
if(isset($sockets[$AnImage])) {
if(feof($sockets[$AnImage])) {
if(!isset($sizes[$AnImage])) $sizes[$AnImage]='';
$sizes[$AnImage].=fgets($sockets[$AnImage], 4096);
// echo("<div>HTML $AnImage DONE.</div>");
// echo("<div>[ ".$sizes[$AnImage]." ]</div>");
// flush();
fclose($sockets[$AnImage]);
unset($sockets[$AnImage]);
$mysizes=ContentLoader::cleanResponse($sizes[$AnImage]);
// echo($sizes[$AnImage]." ");
// echo(ContentLoader::cleanResponse($sizes[$AnImage]));
if(!is_array($mysizes)) {continue;}
if($mysizes[0]>64 && $mysizes[1]>64 && ($mysizes[0]>128 || $mysizes[1]>128))
$FoundImagePaths2[]=array('kind'=>'image','url'=>$AnImage,'ext'=>$ext,'width'=>$mysizes[0],'height'=>$mysizes[1],'mime'=>$mysizes['mime']);