我需要在PHP中进行并行处理,但PHP不支持它而不安装扩展,所以我使用multi_curl
来实现这一点。
main.php
- 构建一个url数组,这些url都是process.php
,具有不同的$ _GET参数。然后使用multi_curl执行它们。
process.php
- 每个线程的处理逻辑。
我只想知道这是否是一种可行的做事方式。这是迟钝的吗?它会导致很多开销吗?有更明智的方法吗?感谢。
答案 0 :(得分:1)
https://github.com/krakjoe/pthreads
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,比如--prefix = / home / mydir,或者某些发行版有一个/ usr / src / debug这是一个很好的地方诸如此类的事情。你显然想添加--with-mysql之类的东西,但你怎么做取决于你的系统(提示,你可以使用php -i | grep configure> factory.config来保存你当前的php安装配置行并且基于你的自定义构建,知道它抱怨的任何库都不可用是apt-get | yum install away)。
答案 1 :(得分:0)
当然,这是一种可行的做事方式,这就是功能存在的原因。
与往常一样,魔鬼在于细节。多个并发请求将与其他进程竞争并消耗服务器资源;你需要调节并发度。
答案 2 :(得分:0)
考虑到PHP不支持任何合理的多处理,multi_curl似乎是一个很好的解决方案!
答案 3 :(得分:0)
如果你在网络服务器上运行PHP(并且multi_curl可能不可用),一种方式(没有库)使它并行运行脚本就是打开socket到localhost:80并手动让webserver运行你想要的脚本。它们将使用服务器多线程并行运行。然后在循环中收集所有结果,当所有结果都完成时(或在你选择的超时后),你继续。
这是从脚本中获取的一段代码,用于检索网页上引用的所有图像的大小。
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
在此之后,您可以在“线程”继续工作的同时开展自己的业务,然后在循环中继续阅读所有$ socket []并测试EOF。在示例中,稍后在代码中(每个$ AnImage的循环):
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']);
在内存和进程方面以及在速度方面效率不高,但如果单个图像需要几秒钟,则具有20多个图像的整个页面需要相同的几秒钟来测试它们。毕竟,它与PHP并行。