几年来,我一直在使用Heroku托管我的应用程序,但刚开始遇到工作队列积压的问题。我希望我能通过增加运行的工人数量来解决这个问题,这样排队的工作就可以并行完成,但每当我增加工人数量时,除了一个工人外,其他人都会崩溃。
这是我的Procfile:
web: vendor/bin/heroku-php-apache2 public
worker: php /app/artisan queue:restart && php /app/artisan queue:work redis --tries=3 --timeout=30
以下是当我将我的工作人员扩展到大于1的任何值时,服务器日志的输出(在本例中,它只是将其扩展到2个工作人员(:
Mar 16 06:04:51 heroku/worker.1 Starting process with command `php /app/artisan queue:restart && php /app/artisan queue:work redis --tries=3 --timeout=30`
Mar 16 06:04:52 heroku/worker.1 State changed from starting to up
Mar 16 06:04:54 app/worker.1 Broadcasting queue restart signal.
Mar 16 06:04:58 heroku/worker.2 Process exited with status 0
Mar 16 06:04:58 heroku/worker.2 State changed from up to crashed
Mar 16 06:04:58 heroku/worker.2 State changed from crashed to starting
Mar 16 06:05:09 heroku/worker.2 Starting process with command `php /app/artisan queue:restart && php /app/artisan queue:work redis --tries=3 --timeout=30`
Mar 16 06:05:10 heroku/worker.2 State changed from starting to up
Mar 16 06:05:14 app/worker.2 Broadcasting queue restart signal.
Mar 16 06:05:19 heroku/worker.1 Process exited with status 0
Mar 16 06:05:19 heroku/worker.1 State changed from up to crashed
正如您所看到的,两个工作线程都尝试启动,但只有worker.2
处于启动状态。
崩溃的工人尝试每10分钟重新启动一次,结果与上述相同。
当我运行heroku ps
时,我看到的是:
=== worker (Standard-1X): php /app/artisan queue:restart && php /app/artisan queue:work redis --tries=3 --timeout=30 (2)
worker.1: crashed 2021/03/16 06:05:19 -0600 (~ 20m ago)
worker.2: up 2021/03/16 06:05:10 -0600 (~ 20m ago)
(我的普通网络dynos可以上下缩放,所以我不会在这里显示(。
有没有想过会发生什么?我的第一个想法是Heroku有问题,但我意识到事实并非如此。我的第二个想法是,我的员工的Procfile条目可能会造成问题,但我对该条目的了解不够,不知道原因是什么。
同样,这对一个工人来说已经很好地工作了很长一段时间,只有当我试图扩大到一个以上的工人时,才会发生崩溃。无论我尝试扩展到多少员工,只有一个不会崩溃,并且保持活跃,能够接收和处理工作。
其他信息:
- Heroku堆栈:Heroku-18
- Laravel版本:8*
- 队列驱动程序:Redis
更新-我在我的暂存环境中放大了dynos,并且能够在没有任何崩溃的情况下放大和缩小工作人员。现在我想可能存在某种附加冲突或其他问题。如果我发现其他问题,我会更新它(已经联系了Heroku的支持人员(。
问题出在procfile中的php /app/artisan queue:restart
命令上。工人启动和调用的重新启动命令导致信号冲突,最终导致除一名工人外的所有工人崩溃。
我取消了这个命令,现在我可以毫无问题地扩大我的员工规模了。
=== worker (Standard-1X): php /app/artisan queue:work redis --queue=high,default,sync,emails,cron --tries=3 --timeout=30 (2)
worker.1: up 2021/03/17 17:29:32 -0600 (~ 8m ago)
worker.2: up 2021/03/17 17:35:58 -0600 (~ 2m ago)
当部署到Heroku时,dynos会收到SIGTERM信号,该信号会杀死任何延迟进程,然后dynos会重新启动。这意味着php /app/artisan queue:restart
命令是多余和不必要的。
主要的困惑来自Laravel在这里对需要重新启动的队列工作人员的信息的措辞:https://laravel.com/docs/8.x/queues#queue-工人和部署。这在没有像Heroku那样处理dynos的服务器上是必要的。