Laravel重启单个队列

队列处理器是 long-lived 进程,如果代码改变而队列处理器没有重启,新代码是不生效的。laravel建议使用

1
php artisan queue:restart

但是这个操作会关闭所有正在运行的队列处理器,不会重启。但是若有多个队列,有时可能只更新了单个队列处理的代码。那就只需要重启对应队列处理器就行。

队列处理流程如下:(vendor/laravel/framework/src/Illuminate/Queue/Worker.php)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public function daemon($connectionName, $queue = null, $delay = 0, $memory = 128, $sleep = 3, $maxTries = 0)
{
$lastRestart = $this->getTimestampOfLastQueueRestart();
while (true) {
if ($this->daemonShouldRun()) {
$this->runNextJobForDaemon(
$connectionName, $queue, $delay, $sleep, $maxTries
);
} else {
$this->sleep($sleep);
}
if ($this->memoryExceeded($memory) || $this->queueShouldRestart($lastRestart)
|| $this->inStopQueueSet($queue) ) {
$this->stop();
}
}
}
// 临时让指定queue自动关闭,用于重启单个queue
protected function inStopQueueSet($queue) {
return Redis::Sismember("laravel:stop:queues",$queue);
}

重启操作如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public function restart($queue) {
Redis::Sadd("laravel:stop:queues",$queue);
while(true) {
sleep(1);
$worker = $this->getWorkerNum($queue);
if ( $worker == 0) {
echo "active worker: $worker\n";
break;
} else {
echo "active worker: $worker\n";
}
}
Redis::Srem("laravel:stop:queues",$queue);
$configs = $this->getLocalConfig();
$worker = $configs[$queue];
echo "start queue: $queue\n";
$this->process($queue,$worker,false);
}