在PHP的yii2框架中,有时候需要一些异步队列的功能,这篇文章主要写如何自己增加几个文件创建一个基于redis list的异步队列进程。
在yii2的框架里,要用到php-cli进程,需要将Controller放入commands文件夹中,并且使用php ./yii ...
的方式进行调用。
首先创建一个Controller用于启动异步队列,代码如下:
<?php
namespace app\commands\daemon;
use yii\console\Controller;
use Yii;
class DaemonController extends Controller
{
private $running_children_pid = [];
private $running = true;
private static $_master_pid;
public static $pid_file;
private $alarm_times = 0;
private $pid = 0;
public function __construct($id, $module, $config = array())
{
$this->checkPcntl();
static::$pid_file = __DIR__ . "/../../runtime/dasheng_yii_daemon.pid";
parent::__construct($id, $module, $config);
}
//检查环境是否支持pcntl支持
private function checkPcntl()
{
// Make sure PHP has support for pcntl
if (!function_exists('pcntl_signal')) {
$message = 'PHP does not appear to be compiled with the PCNTL extension. This is neccesary for daemonization';
echo $message;
throw new \Exception($message);
}
}
private function killallChildren()
{
foreach ($this->running_children_pid as $pname => $pids) {
foreach ($pids as $pid) {
posix_kill($pid, SIGQUIT);
}
}
}
private function sendWarningMail($msg)
{
try {
Yii::$app->mailer->compose()
->setFrom('***')
->setTo('***')
->setSubject('daemon服务器报警')
->setHtmlBody("<html>$msg</html>")
->send();
} catch (\Exception $e) {
\Yii::warning("【daemon服务器报警】发送预警邮件失败>>>" . $e->getMessage());
}
}
//信号处理函数
public function signalHandler($signo)
{
EchoFormat::out("" . $this->pid . " signalHandler($signo)");
switch ($signo) {
//子进程结束信号,可能会有多个子进程结束,用同一个信号,所以while里也要wait
case SIGCHLD:
$stopped_pid = pcntl_wait($status, WNOHANG);
EchoFormat::out($this->pid." wait pid=".$stopped_pid);
$this->removePid($stopped_pid);
//发送报警
if($this->running)
{
EchoFormat::out("running");
++$this->alarm_times;
switch ($this->alarm_times)
{
case 1:
case 10:
case 100:
$ip_info = shell_exec('ifconfig');
$this->sendWarningMail("<pre>$ip_info</pre>");
break;
default:
break;