并行运行多个PHP进程

时间:2012-10-25 13:40:08

标签: php parallel-processing

我们正在研究PHP中的SEO相关脚本,我们需要在完成爬网过程后同时运行不同的模块(每个模块都是一个文件.php)。 换句话说,我们需要并行执行10个以上的.php文件。

用于处理序列的应用程序,因此一旦脚本结束,用户的浏览器就会被转发到下一个脚本。每个脚本都建立与数据库的连接,并将不同的HTTP数据包发送到已爬网的Web应用程序。

据我所知,这可以用popen来解决?有没有办法从每个模块接收信息到触发它们的主脚本?任何人都可以提供一个非常简短的片段来看看它是如何工作的吗?

2 个答案:

答案 0 :(得分:1)

尝试使用此技术在PHP中运行多个并行作业。在这个例子中,我们有两个作业文件:j1.php和j2.php我们想要运行。样本工作没有做任何花哨的事情。 j1.php文件如下所示:

$jobname = 'j1';
set_time_limit(0);
$secs = 60;

while ($secs) {
        echo $jobname,'::',$secs,"\n";
        flush(); @ob_flush();  ## make sure that all output is sent in real-time
        $secs -= 1;
        $t = time();
        sleep(1); // pause
}

我们flush()的原因; @ob_flush();当我们回显或打印时,字符串有时会被PHP缓冲,直到稍后才发送。这两个功能可确保立即发送所有数据。

然后我们有第三个文件control.php,它协调作业j1和j2。此脚本将使用JobStartAsync()中的fsockopen异步调用j1.php和j2.php,因此我们可以并行运行j1.php和j2.php。使用JobPollAsync()将j1.php和j2.php的输出返回给control.php。

#
# control.php
#
function JobStartAsync($server, $url, $port=80,$conn_timeout=30, $rw_timeout=86400)
{
    $errno = '';
    $errstr = '';

    set_time_limit(0);

    $fp = fsockopen($server, $port, $errno, $errstr, $conn_timeout);
    if (!$fp) {
       echo "$errstr ($errno)<br />\n";
       return false;
    }
    $out = "GET $url HTTP/1.1\r\n";
    $out .= "Host: $server\r\n";
    $out .= "Connection: Close\r\n\r\n";

    stream_set_blocking($fp, false);
    stream_set_timeout($fp, $rw_timeout);
    fwrite($fp, $out);

    return $fp;
}

// returns false if HTTP disconnect (EOF), or a string (could be empty string) if still connected
function JobPollAsync(&$fp) 
{
    if ($fp === false) return false;

    if (feof($fp)) {
        fclose($fp);
        $fp = false;
        return false;
    }

    return fread($fp, 10000);
}

###########################################################################################


if (1) {  /* SAMPLE USAGE BELOW */

    $fp1 = JobStartAsync('localhost','/jobs/j1.php');
    $fp2 = JobStartAsync('localhost','/jobs/j2.php');


    while (true) {
        sleep(1);

        $r1 = JobPollAsync($fp1);
        $r2 = JobPollAsync($fp2);

        if ($r1 === false && $r2 === false) break;

        echo "<b>r1 = </b>$r1<br>";
        echo "<b>r2 = </b>$r2<hr>";
        flush(); @ob_flush();
    }

    echo "<h3>Jobs Complete</h3>";
}

好读

Divide-and-conquer and parallel processing in PHP

from the source

答案 1 :(得分:1)

如果PHP中的各种文件没有依赖关系,我认为您可以使用多卷曲方法,可以如图所示实现: -

    $linkArray = array('file1.php', 'file2.php','file3.php','file4.php','file5.php');
    $nodes = ($linkArray);
    $node_count = count($nodes);

    $curl_arr = array();
    $master = curl_multi_init();
    $counter = 0;
    for($i = 0; $i < $node_count; $i++)
    {
      $url =$nodes[$i];
      $curl_arr[$i] = curl_init($url);
      curl_setopt($curl_arr[$i], CURLOPT_RETURNTRANSFER, true);
      curl_multi_add_handle($master, $curl_arr[$i]);
    }

do {
    curl_multi_exec($master,$running);
} while($running > 0);

for($k=0;$k<$node_count;$k++){

  $result = curl_multi_getcontent  ($curl_arr[$k]); // contains the output of individual files

}