将PHP数组分成几部分并异步运行块?

时间:2015-02-23 18:55:32

标签: php arrays asynchronous

我想取一个数组并将其分解成块(闭包$ r完成此操作)

/**
 * Breaks an array into bits
 *
 * @param $list
 * @param $p
 * @return array
 */
$r = function ($list, $p)
{
    $ll = count( $list ); $pl = floor( $ll / $p ); $pt = $ll % $p; $r = []; $m = 0;

    for ($px = 0; $px < $p; $px++)
    {
        $inc = ($px < $pt) ? $pl + 1 : $pl; $r[$px] = array_slice( $list, $m, $inc );
        $m += $inc;
    }

    return $r;
};

$hosts = [
    'devhost-0',
    'devhost-1',
    'devhost-2',
    'devhost-3',
    'devhost-4',
    'devhost-5',
    'devhost-6',
    'devhost-7',
    'devhost-8',
    'devhost-9',
    'devhost-10',
    'devhost-11',
    'devhost-12',
    'devhost-13',
    'devhost-14',
    'devhost-15',
    'devhost-16',
    'devhost-17',
    'devhost-18',
    'devhost-19',
    'devhost-20',
    'devhost-21',
    'devhost-22',
    'devhost-23',
    'devhost-24',
    'devhost-25',
    'devhost-26',
    'devhost-27',
    'devhost-28',
    'devhost-29',
    'devhost-30',
    'devhost-31',
    'devhost-32',
    'devhost-33',
    'devhost-34',
    'devhost-35',
    'devhost-36',
];

$hosts = $r($hosts, 6); // chunks of six

这将打破上面的array into chunks of 5-6,从这里我想同时运行每个块 用一个简单的方法,让我们说下面的ping闭包。

/**
 * Polls host
 *
 * @param $host
 * @param $port
 * @param $timeout
 * @return bool
 */
$ping = function ($host, $port, $timeout)
{
    $errno = $errstr = false; // silence....
    return (! @fSockOpen($host, $port, $errno, $errstr, $timeout))
        ? false
        : true;
};

我不知道怎么做到这一点?我会假设我会使用pcntl_fork()pthreads,但不确定我应该如何设置它?我已经异步阅读了多篇关于运行进程的文章,但我在查找一个使用数组作为示例中的部分时遇到了问题。

2 个答案:

答案 0 :(得分:2)

我认为这可行(基于此处的线程示例http://acm.msu.ru/mkoshp/php-chunked-xhtml/pthreads.tutorials.html

$hosts = [
    'devhost-0',
    'devhost-1',
    'devhost-2',
    'devhost-3',
    'devhost-4',
    'devhost-5',
    'devhost-6',
    'devhost-7',
    'devhost-8',
    'devhost-9',
    'devhost-10',
    'devhost-11',
    'devhost-12',
    'devhost-13',
    'devhost-14',
    'devhost-15',
    'devhost-16',
    'devhost-17',
    'devhost-18',
    'devhost-19',
    'devhost-20',
    'devhost-21',
    'devhost-22',
    'devhost-23',
    'devhost-24',
    'devhost-25',
    'devhost-26',
    'devhost-27',
    'devhost-28',
    'devhost-29',
    'devhost-30',
    'devhost-31',
    'devhost-32',
    'devhost-33',
    'devhost-34',
    'devhost-35',
    'devhost-36',
];
class Devhost_worker extends Thread{
    public $jobs;
        public function __construct($jobs) {
       $this->jobs = $jobs;
    }
        public function run() {
        //do your stuff with the $this->jobs  here.
    }
}
$chunks=array_chunk($hosts,6,true);
$threads=array();
$i=0;
foreach($chunks as $chunk){
    $threads[$i]=new Devhost_worker($chunk);
    $threads[$i]->start();
}

答案 1 :(得分:0)

我刚才提出的一些事情,不会接受,但会作为我的问题的可能解决方案发布。我能在大约1分钟左右的时间内ping掉4k服务器。

<?php

define('APP_DIR', dirname(__DIR__)); // autloads in non-sample script....

$hosts = explode("\n", file_get_contents(APP_DIR . '/data/test.txt'));

/**
 * Processes in Parallel.
 *
 * Run a function (with no return result) on each item in an array in parallel.
 * Note: This function is only useful if order is not important, and you don't
 * need any return values from the function (i.e. no inter-process communication).
 *
 * @param mixed   $func  A closure function to apply to each item in parallel.
 * @param array   $arr   The array to apply function to.
 * @param integer $procs Number of processes to run in parallel.
 *
 * @return void
 */
function parallelize($func, array $arr, $procs = 4)
{
    $chunks   = array_chunk($arr, ceil((count($arr) / $procs)));
    $pid      = -1;
    $children = [];
    foreach ($chunks AS $items)
    {
        $pid = pcntl_fork();

        switch ($pid)
        {
            case (-1): die ('Unable to fork');

            case (0): // We are the child process. Pass a chunk of items to process.
                array_walk($items, $func);
                exit(0);

            default: // We are the parent.
                $children[] = $pid;
                break;
        }
    }

    // Wait for children to finish.
    foreach ($children AS $pid)
    {
        // We are still the parent.
        pcntl_waitpid($pid, $status);
    }
}

/**
 * Polls host
 *
 * @param $host
 * @param $port
 * @param $timeout
 * @return bool
 */
$ping = function ($host, $port, $timeout)
{
    $errno = $errstr = false; // silence....
    return (! @fSockOpen($host, $port, $errno, $errstr, $timeout))
        ? false
        : true;
};


/**
 * Simple true false return on pinging...
 *
 * @param $host
 * @return bool
 */
$tap = function ($host) USE ($ping)
{
    if (! $ping($host, 22, 3))
    {
        echo "[fail] does not exist\n";
        return false;
    }

    else
    {
        echo "[good] exists\n";
        return true;
    }
};

parallelize($tap, $hosts, 20); // do work....