队列 + Horizon 使用问题

1. 运行环境

win10 + VirtualBox + Homestead

1). 当前使用的 Laravel 版本?

8.83.19

2). 当前使用的 php/php-fpm 版本?

PHP 版本:7.4.26
php-fpm 版本:

3). 业务环境

local 本地开发环境

2. 问题描述?

目前状况是,通过触发Job里的代码,循环往队列加入任务,结果就是基本只有最后加入的任务才能执行完成,先入队的大部分任务只会执行一半左右就莫名卡住不动了,一直挂到retry_after设置的超时时间后,直接进入失败列表。官方文档对这块功能写的非常模糊,并没有明确写出每一项配置的作用,所以我不能确定我配置的是否有问题,目前尝试过调大horizon.php下的memory_limit内存与maxProcesses最大进程数,依旧无效,每次更改配置或更新job代码后,也会执行重启虚拟机和清空缓存等命令,应该不是缓存造成的,failed_job表中记录的都是“has been attempted too many times or run too long”超时错误,看不出卡死的原因,
有遇到相同问题的朋友帮忙看看问题大概是出在哪吗?非常感谢。

queue.php 配置

'default' => env('QUEUE_CONNECTION', 'redis'),

'connections' => [
    'redis' => [
        'driver' => 'redis',
        'connection' => 'queue',
        'queue' => 'default',
        'retry_after' => 350,
        'block_for' => null,
        'after_commit' => false,
    ],
],

horizon.php 配置

    'memory_limit' => 512,

    'defaults' => [
        'picContrast' => [
            'connection' => 'redis',
            'queue' => ['default', 110000, 310000, 320000, 330000],
            'balance' => 'auto',
            'memory' => 512,
            'tries' => 1,
            'nice' => 0,
        ],
    ],

    'environments' => [
        'production' => [
            'picContrast' => [
                'minProcesses' => 1,
                'maxProcesses' => 300,
                'balanceMaxShift' => 1,
                'balanceCooldown' => 3,
            ],
        ],

        'local' => [
            'picContrast' => [
                'minProcesses' => 1,
                'maxProcesses' => 300,
                'balanceMaxShift' => 1,
                'balanceCooldown' => 3,
            ],
        ],
    ],

database.php 配置

'redis' => [
        'client' => 'predis',
        'cluster' => false,
        'queue' => [
            'host' => '127.0.0.1',
            'password' => null,
            'port' => 6379,
            'database' => 0,
        ],
    ],

触发Job

for ($i = 1; $i <= 10; $i++) {
    test::dispatch([])->onQueue(110000);
}

Job实现

class test implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries = 1;

    public $timeout = 300;

    public function __construct($parameter = [])
    {
        // ...
    }

    public function handle()
    {
        for ($i = 0; $i <= 100; $i++) {
            sleep(2);
            Log::channel('test')->info('apiError', [$i]);
        }
    }
}

重启环境,清空缓存

vagrant reload
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan queue:clear
php artisan horizon:clear
php artisan horizon:terminate
php artisan horizon

Horizon 面板

3. 您期望得到的结果?

加入多个任务并行也不会导致先进入队列的任务卡死

4. 您实际得到的结果?

同时添加多个任务后,先添加的任务会中断卡死,一直挂到 retry_after 设置的超时时间进入失败列表。

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

最后尝试发现是 horizon.php 配置中 balance 设置的问题,从 “auto” 改为 “simple” 就好了,在此之前无论怎么调整,都会出现多任务莫名卡死问题,具体原因不太清楚。有遇到相同问题的朋友,可以尝试改成simple试试。

9个月前 评论
讨论数量: 5

我也遇到这个问题

1年前 评论

可以试试设置horizon任务的超时时间:

'defaults' => [
    'picContrast' => [
        'connection' => 'redis',
        'queue' => ['default', 110000, 310000, 320000, 330000],
        'balance' => 'auto',
        'memory' => 512,
        'tries' => 1,
        'nice' => 0,
        'timeout' => 350
    ],
],
1年前 评论

maxProcesses太大了,要改为1,就行了

1年前 评论

个人推测一下,sleep 的阻塞应该是被所有 process 进程甚至 horizon 本身的主进程“共享”的。

也就是 process 进程在交替使用 sleep 进行阻塞,所以结果就是几个任务一起超时了。

1年前 评论

最后尝试发现是 horizon.php 配置中 balance 设置的问题,从 “auto” 改为 “simple” 就好了,在此之前无论怎么调整,都会出现多任务莫名卡死问题,具体原因不太清楚。有遇到相同问题的朋友,可以尝试改成simple试试。

9个月前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!