2

我需要在 PHP 中进行并行处理,但是如果没有安装扩展,PHP 不支持它,所以我正在使用它multi_curl来实现这一点。

main.php- 构建一个 url 数组,它们都process.php具有不同的 $_GET 参数。然后使用 multi_curl 执行它们。

process.php- 每个线程的处理逻辑。

我只是想知道这是否是一种可行的做事方式。这是迟钝吗?它会导致很多开销吗?有没有更明智的方法来做到这一点?谢谢。

4

4 回答 4

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 )。

于 2012-09-19T15:32:00.703 回答
0

当然,一般来说,这是一种可行的做事方式,这就是功能存在的原因。

一如既往,魔鬼在细节中。多个并发请求会与其他进程竞争并消耗服务器资源;您将需要调节并发程度。

于 2012-09-18T14:49:23.983 回答
0

考虑到 PHP 不以任何合理的方式支持多处理,multi_curl 在您的情况下似乎是一个很好的解决方案!

于 2012-09-18T14:49:34.860 回答
0

如果您在 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

在此之后,您可以在“线程”继续工作的同时做自己的事情,然后,在一个循环中,您继续读取所有 $sockets[] 并测试 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。

于 2014-02-06T10:17:31.747 回答