首页 > 解决方案 > Laravel 队列守护进程不断使用 DB 处理器(supervisord)

问题描述

我正在使用以下配置运行我们的 Laravel 队列守护程序(本质上是低容量的电子邮件作业),但我注意到我们的 Amazon RDS 服务器上的 CPU 使用率恒定,这取决于正在运行的队列进程的数量。每个都贡献了 RDS 实例上4.3% 的恒定CPU 使用率。所以在过去的几周里,我们一直在不停地使用 9% 的 CPU。

队列大部分是空的,只是偶尔有一些电子邮件作业要发出,但队列工作人员不断地向数据库扔工作!当进程数为 1 时,它下降到 4.3% 不变,所以它肯定是队列工作者。

有人有这个问题吗?

[program:example-queue]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/example.com.au/artisan queue:work database --sleep=3 --tries=3 --daemon
autostart=true
autorestart=true
user=ubuntu
numprocs=2
redirect_stderr=true
stdout_logfile=/root/queue.log

Amazon RDS CPU 使用情况图

标签: mysqllaravelqueueamazon-rds

解决方案


实际上这不是问题,而是它如何与多个流程的组合一起工作(在您的案例主管中)。Laravel 的数据库队列驱动程序不断(在您的情况下不包括 3 秒睡眠)不断select在您的服务器上查询()以获取可用的作业。如果将其替换为,redis那么相同的进程将不断地在 redis 服务器上执行 sorted set( zrangebyscore, zremrangebyscore) 和 list( lpop) 命令来查询队列。

以下方法来自 DatabaseQueue。

protected function getNextAvailableJob($queue)
{
    $job = $this->database->table($this->table)
                ->lockForUpdate()
                ->where('queue', $this->getQueue($queue))
                ->where(function ($query) {
                    $this->isAvailable($query);
                    $this->isReservedButExpired($query);
                })
                ->orderBy('id', 'asc')
                ->first();

    return $job ? new DatabaseJobRecord((object) $job) : null;
}

既然你说“有一些电子邮件工作要发布”,

您可以;

  • 增加--sleep
  • 减少进程数
  • 在没有主管的情况下运行您的 queue:work 命令,例如绑定到minutely cron.
  • 切换到 redis 队列驱动程序(它不会在您的数据库上产生开销),AWS ElastiCachecache.t2.micro将绰绰有余,您无需支付任何费用(一年),因为它是 12 个月的免费套餐。

推荐阅读