Laravel生产服务器运行队列的正确方式及queue:work命令引发504超时与服务器崩溃的解决咨询
兄弟,我太懂你这种本地跑的好好的,一上生产就崩的糟心劲儿了!针对你说的queue:work在生产环境引发504超时、服务器崩溃的问题,我给你梳理几个实用的排查和解决方向:
先确认队列驱动的配置与服务状态
本地可能用的是sync或者database驱动,生产环境如果切换到了redis、beanstalkd这类异步驱动,一定要先确认对应的服务在生产服务器上是正常运行的。同时检查.env文件里的QUEUE_CONNECTION是不是配置正确,比如用Redis的话,主机、端口、密码这些参数有没有填对,别因为驱动连接不上导致任务堆积崩服务器。绝对不要直接在终端跑
queue:work!用进程管理器守护进程
生产环境直接跑queue:work是大忌——终端一关进程就停,而且单进程扛不住大量任务时很容易超时崩溃。推荐用supervisor或者systemd来管理队列进程,这里给你个supervisor的配置示例:
创建配置文件/etc/supervisor/conf.d/laravel-queue.conf,内容如下:[program:laravel-queue] process_name=%(program_name)s_%(process_num)02d command=php /你的项目绝对路径/artisan queue:work redis --sleep=3 --tries=3 --max-time=3600 autostart=true autorestart=true user=www-data # 改成你的服务器运行PHP的用户 numprocs=4 # 根据服务器配置调整进程数,别开太多占资源 redirect_stderr=true stdout_logfile=/你的项目绝对路径/storage/logs/queue.log配置好后重启supervisor服务,它会自动帮你守护队列进程,挂了自动重启,多进程并行处理任务也能避免单进程过载。
优化任务本身,设置合理的超时时间
如果你是给大量用户发邮件,单个任务处理的用户数是不是太多了?可以拆成小批量任务来执行。另外,给队列任务设置超时限制:要么在启动命令里加--timeout=60(单位秒),要么在你的邮件任务类里定义public $timeout = 60;,防止单个任务卡住太久拖垮整个队列。检查服务器资源与Web服务器超时设置
先看看服务器的CPU、内存够不够——用top或者htop命令监控queue:work进程的资源占用,如果内存吃满了,要么升级服务器配置,要么减少supervisor的进程数。另外,504超时大概率和Nginx/Apache的超时设置有关,比如Nginx的proxy_read_timeout默认是60秒,要是队列任务执行超过这个时间就会返回504,你可以把这个值改成300秒甚至更长,重启Web服务器试试。靠日志定位具体问题
别瞎猜,直接看日志!Laravel的storage/logs/laravel.log里会有任务执行的详细报错,比如是不是数据库连接超时、邮件服务器连不上导致任务卡住,或者某个代码逻辑有问题。同时也看看服务器的系统日志,能帮你快速定位到底是资源问题还是代码问题。
备注:内容来源于stack exchange,提问作者Bhola Seema

