Laravel/Lumen 任务调度简易入门说明

前提

Laravel 中任务调度简化了服务器系统中 Cron 的操作,使得 计划任务 的实现更为简便。

这里主要以 Laravel 自带的消息队列进行说明,了解其间运行关系可以让我们更清晰的进行代码实现。

下方代码以 Lumen 9.x 框架进行举例,与 Laravel 应无二致。

中文参考文档:任务调度 - Laravel 9.x

定义任务调度

我们称之为 计划任务周期性任务 均可。因为他的目的即是如此。

首先编辑 App\Console\Kernel 类,默认内容如下:

php 复制代码
<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel {

    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
    ];

    /**
     * Define the application's command schedule.
     *
     * @param Schedule $schedule
     *
     * @return void
     */
    protected function schedule(Schedule $schedule): void {
        // TODO:
    }
}

例如我们需要在 每周一凌晨时段 执行业务统计任务(假设统计上一周订单量、销售额)

周期定义可参阅:任务调度 - 调度频率选项

schedule 方法中先写上如下代码:

php 复制代码
protected function schedule(Schedule $schedule): void {
    $schedule->job()                // 到达指定周期执行的目标任务,此处我们的目的是生产一条消息队列
        ->withoutOverlapping()      // 避免任务重复
        ->timezone('Asia/Shanghai') // 指定时区
        ->weeklyOn([1], '03:00');   // 定义时间:每周一 03:00 AM 执行。如果周一、周三、周六皆需要运行则可将第一参数修改为 [1, 3, 6]
}

IDE 会对 job 方法报出警告,因为我们还未添加其对应的消息队列

添加消息队列

Laravel/Lumen 框架中支持多种消息队列驱动:sqsdatabaseredisbeanstalkd,我们以 redis 为例。此处假设你已做好 redis 队列相关环境以及配置。

我们在 App\Jobs 中编写一个 WeeklyStatisticsJob 类:

php 复制代码
<?php

namespace App\Jobs;

class WeeklyStatisticsJob extends Job {

    public function __construct() {
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle(): void {
        // TODO:

        echo "done\n";

        $this->delete();
    }
}

如需传递自定义参数至该 Job 类,只需在 __construct 方法中添加形参相应,并传递至成员变量,例如:

php 复制代码
<?php

namespace App\Jobs;

class WeeklyStatisticsJob extends Job {

    private int $supplierId;
    private string $beginDate;
    private string $endDate;

    public function __construct(int $supplier_id, string $begin_date, string $end_date) {
        $this->supplierId = $supplier_id;
        $this->beginDate = $begin_date;
        $this->endDate= $end_date;
    }
}

TODO: 部分为实际业务代码,例如调用服务类实现统计并存储于数据库中。

应用消息队列

回到 App\Console\Kernel 类,将消息队列类实例化进 job 方法即可:

php 复制代码
protected function schedule(Schedule $schedule): void {
    $schedule->job(new WeeklyStatisticsJob(1, '2023-11-13', '2023-11-19'))
        ->withoutOverlapping()
        ->timezone('Asia/Shanghai')
        ->weeklyOn([1], '03:00');
}

注意 ,我们为了将其与已有消息队列进行区分,应对其指定单独的队列名称。同样,如果需要单独指定消息队列的连接(使用 databasesqs 等),还需指定连接名。

所以我们应当修改为:

php 复制代码
protected function schedule(Schedule $schedule): void {
    $schedule->job(
        new WeeklyStatisticsJob(1, '2023-11-13', '2023-11-19'),
        'weekly_calc_statistics',  // 建议指定队列名称,如未指定,默认为 'default'
        'redis'                    // 默认使用 redis 时,此处可忽略
    )
        ->withoutOverlapping()
        ->timezone('Asia/Shanghai')
        ->weeklyOn([1], '03:00');
}

至此,我们的周期任务就已编写完成,但对于测试来说,周期过于漫长,我们可以将 每周一凌晨三点 修改为每分钟,或者每 5-10 分钟进行测试。

即,将 weeklyOn([1], '03:00') 修改为 everyMinute()everyFiveMinute() 等方法。

运行测试

我们首先应当运行上方编写的队列监听:weekly_calc_statistics

在项目根目录中执行下方命令:

bash 复制代码
# 如未指定队列名,可忽略 queue 参数
php artisan queue:work --queue=weekly_calc_statistics

随后在 另一 命令窗口中执行:

bash 复制代码
php artisan schedule:work

稍等片刻,周期任务将生产一条消息队列放入 redis 中,随后可在消息队列命令窗口中看到该队列被消费提示。

相关推荐
Hello.Reader2 小时前
RedisJSON 路径语法深度解析与实战
数据库·redis·缓存
TDengine (老段)2 小时前
TDengine 使用最佳实践(2)
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
zorro_z2 小时前
PHP语法高级篇(二):文件处理
php
SuperherRo5 小时前
Web攻防-PHP反序列化&原生内置类&Exception类&SoapClient类&SimpleXMLElement
php·xss·反序列化·exception·ssrf·原生类·soapclient
设计师小聂!5 小时前
Linux系统中部署Redis详解
linux·运维·数据库·redis
kfepiza5 小时前
Debian-10编译安装Mysql-5.7.44 笔记250706
linux·数据库·笔记·mysql·debian·bash
Touper.5 小时前
Redis 基础详细介绍(Redis简单介绍,命令行客户端,Redis 命令,Java客户端)
java·数据库·redis
不剪发的Tony老师5 小时前
phpMyAdmin:一款经典的MySQL在线管理工具又回来了
数据库·mysql·phpmyadmin
极限实验室5 小时前
TDBC 2025 可信数据库发展大会,极限科技邀您来赴约!
数据库
lixia0417mul27 小时前
使用Starrocks替换Clickhouse的理由
数据库