Хочу показать свой базовый класс, который я использую для PHP скриптов.
Приемущество его в том, что легко можно «распараллелить» работу.
Используется pcntl_fork() со всеми «вытекающими».
(тестировалось только на линукс)
в итоге получим один родительский процесс и 5 дочерних делающих «heavy job».
Есть свои нюансы и ограничения: открытые соединения с базой и файлы могут свести сума.
Нужен другой подход: родительский процесс должен заниматься базой и дочерние процессы делать «черную работу» и возвращать результат. Вот например:
Быстрое пояснение, если кто запутался:
после старта в родительском процессе выполняется метод processMaster(), который стартует дочерние процессы.
В дочернем процессе выполняется метод processWorker().
То, что дочерний процесс возвращает — сохраняется во временном файле, после завершения вызывается метод processResult() в родителе и передается туда результат.
в классе CliScript есть несколько полезных методов:
getRunningTime() возвращает время выполнения от старта в секундах
countWorkers() возвращает количество дочерних процессов (имеет смысл только в родтельском процессе)
log() если задан файл CliScript::$file_log то логируется, если нет — на экран. Выводится информация о том, «кто сообщает»
Чтобы убить всю компанию «нежно» отправте сигнал SIGTERM родительскому процессу, там есть примитивный обработчик.
Не могу сказать что код обкатанный и вылизаный, скорее наоборот, но мне он очень помогает быстренько загрузить CPU работой когда надо.
исходник класса CliScript
Если у кого-то есть похожие наработки и готов поделится — буду очень рад.
Приемущество его в том, что легко можно «распараллелить» работу.
Используется pcntl_fork() со всеми «вытекающими».
(тестировалось только на линукс)
Суть идеи:
class some_script extends CliScript
{
protected function processWorker($item)
{
$this->log("I'm doing heavy job");
sleep(rand(1,5));
$this->log("I'm done doing heavy job");
}
}
$script = new some_script();
$script->setWorkers(5);
$script->run();
в итоге получим один родительский процесс и 5 дочерних делающих «heavy job».
Есть свои нюансы и ограничения: открытые соединения с базой и файлы могут свести сума.
Нужен другой подход: родительский процесс должен заниматься базой и дочерние процессы делать «черную работу» и возвращать результат. Вот например:
class master_and_workers extends CliScript
{
protected $contracts = array(2,4,5,1,3,7,3,1,4,9,2,4,1);
protected $results;
protected function processMaster()
{
foreach($this->contracts as $contract)
{
while( !$this->canStartWorker() ) { sleep(1); };
$this->startWorker($contract);
}
$this->waitForChildren();
var_export($this->results);
}
protected function processWorker($item)
{
$this->log("I'm busy for {$item} seconds...");
sleep($item);
$this->log("Job is done.");
return "Job is done. Sleep time was {$item}";
}
protected function processResult($result)
{
$this->results[] = $result;
}
}
$script = new master_and_workers();
$script->setWorkers(3);
$script->run();
Быстрое пояснение, если кто запутался:
после старта в родительском процессе выполняется метод processMaster(), который стартует дочерние процессы.
В дочернем процессе выполняется метод processWorker().
То, что дочерний процесс возвращает — сохраняется во временном файле, после завершения вызывается метод processResult() в родителе и передается туда результат.
в классе CliScript есть несколько полезных методов:
getRunningTime() возвращает время выполнения от старта в секундах
countWorkers() возвращает количество дочерних процессов (имеет смысл только в родтельском процессе)
log() если задан файл CliScript::$file_log то логируется, если нет — на экран. Выводится информация о том, «кто сообщает»
Чтобы убить всю компанию «нежно» отправте сигнал SIGTERM родительскому процессу, там есть примитивный обработчик.
В завершение.
Не могу сказать что код обкатанный и вылизаный, скорее наоборот, но мне он очень помогает быстренько загрузить CPU работой когда надо.
исходник класса CliScript
Если у кого-то есть похожие наработки и готов поделится — буду очень рад.