You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为所有动态队列运行Laravel队列Worker?

动态处理Laravel多队列任务的方案

针对你这种多客户独立数据库、队列名动态生成(DatabaseName~modulename)的场景,提供以下两种实用解决方案:

方案一:自定义Artisan命令批量加载队列名

通过编写自定义命令,自动从secret_databases的jobs表中提取所有存在的队列名,传递给queue:work统一处理。

步骤1:创建自定义命令

执行Artisan命令生成新命令文件:

php artisan make:command QueueWorkAll

步骤2:编写命令逻辑

修改app/Console/Commands/QueueWorkAll.php文件内容:

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Cache;

class QueueWorkAll extends Command
{
    protected $signature = 'queue:work-all {--timeout=60} {--sleep=3} {--tries=3}';
    protected $description = 'Process all dynamic queues from secret_databases';

    public function handle()
    {
        // 从缓存或数据库获取所有唯一队列名,缓存5分钟减少数据库查询压力
        $queues = Cache::remember('dynamic_queues', 300, function () {
            return DB::connection('secret_databases')
                ->table('jobs')
                ->distinct()
                ->pluck('queue')
                ->filter() // 过滤空队列值
                ->implode(',');
        });

        if (empty($queues)) {
            $this->info('No active queues found. Exiting.');
            return;
        }

        $this->info("Starting worker for queues: {$queues}");

        // 启动队列工作进程,处理所有队列任务
        Artisan::call('queue:work', [
            '--queue' => $queues,
            '--timeout' => $this->option('timeout'),
            '--sleep' => $this->option('sleep'),
            '--tries' => $this->option('tries'),
        ]);
    }
}

步骤3:配置缓存刷新(可选)

当有新队列任务分发时,清除缓存以立即加载新队列名:

// 在任务分发的代码处添加以下逻辑
Cache::forget('dynamic_queues');

步骤4:用Supervisor管理进程

由于队列名会随新客户/模块新增,通过Supervisor定时重启命令来加载新队列。示例Supervisor配置:

[program:laravel-queue-all]
process_name=%(program_name)s
command=php /path/to/your/project/artisan queue:work-all --timeout=60 --sleep=3 --tries=3
autostart=true
autorestart=true
user=your-server-user
redirect_stderr=true
stdout_logfile=/path/to/your/project/storage/logs/queue-all.log
stopsignal=INT
stopwaitsecs=3600
; 每小时重启一次,确保加载新队列
startsecs=3600

方案二:循环轮询动态队列

如果需要实时响应新队列,可以让命令持续运行,每隔一段时间重新获取队列列表并处理任务。

修改QueueWorkAll.php的handle方法:

public function handle()
{
    $this->info('Starting dynamic queue worker loop...');

    while (true) {
        // 实时获取队列名(不缓存)
        $queues = DB::connection('secret_databases')
            ->table('jobs')
            ->distinct()
            ->pluck('queue')
            ->filter()
            ->implode(',');

        if (empty($queues)) {
            $this->info('No queues found. Sleeping for 60 seconds...');
            sleep(60);
            continue;
        }

        $this->info("Processing queues: {$queues}");

        // 单次处理任务后退出,再重新获取队列
        Artisan::call('queue:work', [
            '--queue' => $queues,
            '--timeout' => $this->option('timeout'),
            '--sleep' => $this->option('sleep'),
            '--tries' => $this->option('tries'),
            '--once' => true,
        ]);

        // 短暂休眠避免频繁查询数据库
        sleep(5);
    }
}

这种方式无需频繁重启Supervisor,但会持续占用一个进程,适合队列任务新增频繁的场景。

注意事项

  • 确保secret_databases数据库连接在config/database.php中配置正确。
  • 当队列数量极多(如400+)时,一次性传递所有队列名给queue:work会按顺序处理队列,若某队列任务积压会导致其他队列延迟。可根据业务分组处理,或启动多个worker进程分散压力。
  • 监控队列日志,及时处理失败任务,可结合queue:failed和queue:retry命令管理失败任务。

内容的提问来源于stack exchange,提问作者Test Test

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 07:45:30