<?php
class Daemon{
protected $pid;
protected $paused = false;
protected $shouldQuit = false;
protected $count = 1;
protected $sigalrm = 3;
protected $now_job = '';
protected $max_count = 3;
protected $now_count = 1;
public function setSigalrm($num = 3){
$this->sigalrm = $num;
}
public function setMaxCount($count){
$this->max_count = $count;
}
protected function handle($job, $is_retry = false)
{
$rand_num = rand(0, 1);
//$rand_num = 0;
if( $rand_num == 0 ){
sleep(5);
}else{
sleep(1);
if($is_retry == false){
echo $job . ": success\n";
}
return 1;
}
}
protected function supportsAsyncSignals()
{
return version_compare(PHP_VERSION, '7.1.0') >= 0 &&
extension_loaded('pcntl');
}
protected function registerTimeoutHandler()
{
if ($this->supportsAsyncSignals()) {
pcntl_signal(SIGALRM, function () {
echo $this->now_job . ': 超时处理失败,正在重试...' . "\n";
if($this->handle($this->now_job, true)){
echo $this->now_job . ': 重试成功!' . "\n";
}else{
echo $this->now_job . ': 超时处理失败,已写入失败表中,并记录日志' . "\n";
}
//$this->kill();
});
pcntl_alarm(3);
}
}
public function kill($status = 0)
{
if (extension_loaded('posix')) {
posix_kill($this->pid, SIGKILL);
}
exit($status);
}
protected function listenForSignals()
{
if ($this->supportsAsyncSignals()) {
pcntl_async_signals(true);
pcntl_signal(SIGINT, function () {
$this->kill();
});
pcntl_signal(SIGTERM, function () {
$this->kill();
});
pcntl_signal(SIGUSR2, function () {
$this->paused = true;
});
pcntl_signal(SIGCONT, function () {
$this->paused = false;
});
}
}
public function daemon()
{
$this->listenForSignals();
for( ; $this->count <= 5; $this->count++){
$this->now_job = 'send email to why' . $this->count;
$this->registerTimeoutHandler();
$this->handle($this->now_job);
}
//print_r($this->max_count);
}
}
set_time_limit(0);
$a = new Daemon();
$a->setSigalrm(3);
$a->daemon();
原理
在handle设置随机数永远为0,也就是永远sleep5秒,所以每次重试都会超过3秒,触发SIGALRM定时器信号,所以每个job失败后默认重试一次,第二次失败写入磁盘。
结果
[weihaoyu@iZ23u681ae1Z openadmin]$ php daemon.php
send email to why1: success
send email to why2: success
send email to why3: 超时处理失败,正在重试...
send email to why3: 超时处理失败,已写入失败表中,并记录日志
send email to why4: 超时处理失败,正在重试...
send email to why4: 重试成功!
send email to why5: 超时处理失败,正在重试...
send email to why5: 超时处理失败,已写入失败表中,并记录日志
[weihaoyu@iZ23u681ae1Z openadmin]$