这里是基于TP的commond实现的class requestLog extends \app\common\think\Command
{
public $works = [];
public $max_precess = 10;//最大进程数
public $new_index = 0;//当前进行数
public $mpid = 0;//父进程id
public $cache_key = '';
protected function configure()
{
$this->setName('requestLog')
//最大进程数
->addArgument('max_process_count', Argument::OPTIONAL, 'max process count',0)
->addOption('daemon','d', Argument::OPTIONAL, 'daemon','start')
->setDescription('save requestlog');
}
protected function execute(Input $input, Output $output)
{
//守护进程
$act = $input->getOption('daemon');
// die();
$this->daemon('',$act);
if ($act=='stop'){
return ;
}
swoole_set_process_name("request log");
$output->comment("start request log");
ini_set('default_socket_timeout', -1);
$this->mpid = posix_getpid();//获取当前进程id
$max_process_count = trim($input->getArgument('max_process_count'));
if ($max_process_count > 0){
$this->max_precess = $max_process_count;
}
$redis = new Redis();
$queue_key = CacheKeys::REQUEST_QUEUE_KEY;//订阅频道key
$this->cache_key = CacheKeys::REQUEST_LOG_CACHE_KEY;
$redis->subscribe(array($queue_key),function ($instance, $channelName, $message) {//订阅redis,收到发布消息,则执行以下方法
$this->runTask();
});
}
private function runTask()
{
if (count($this->works) < $this->max_precess) {//如果未达到最大进程数,则创建,否则回收
$pid = $this->createProcess($this->new_index);//创建进程
if ($pid) {
$this->new_index++;
}
}else{
$this->processWait(false);//开始回收
}
}
protected function createProcess($index = null,$cache=null)
{
echo 'start process'.PHP_EOL;
$process = new \swoole_process(function (\swoole_process $worker) use ($index) {
$this->clacData();//处理业务的代码
$this->checkMpid($worker, $index);//检测当前进程是否存在,如果不存在则回收
}, false, false);
$pid = $process->start();
if ($pid) {
$this->works[$index] = $pid;
}
$this->processWait(false);//回收结束运行的子进程。
return $pid;
}
/**
* Notes :检测父级进程是否存在,如果不存在则结束当前子进程
* @param $worker
* @param $index
* author: leojen
* @date: 18-4-19 下午6:30
*/
public function checkMpid(&$worker, $index)
{
if (!\swoole_process::kill($this->mpid, 0)) {
$worker->exit(0);
unset($this->works[$index]);
}
}
/**
* Notes : 回收进程
* @param bool $blocking 是否阻塞 默认是
* author: leojen
* @date: 18-4-19 下午6:17
*/
public function processWait($blocking = true)
{
if (count($this->works)) {
$ret = \swoole_process::wait($blocking);//回收子进程,操作成功会返回一个数组包含子进程的PID、退出状态码、被哪种信号KILL,失败返回false
if ($ret && isset($ret['pid'])) {
$index = array_search($ret['pid'], $this->works);
unset($this->works[$index]);
echo "this [{$ret['pid']}] aready quit \r\n";
}
}
}
/**
* Notes :
* @param null $redis
* author: leojen
* @date: 18-4-19 下午6:52
*/
private function clacData()
{
//业务逻辑代码
}
}