我想取一个数组并将其分解成块(闭包$ 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,但不确定我应该如何设置它?我已经异步阅读了多篇关于运行进程的文章,但我在查找一个使用数组作为示例中的部分时遇到了问题。
答案 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....