定时任务

    说明

    在实际项目中,我们经常会有一些任务是需要定时执行的。

    虽然有 croncrontabsystemd 等系统级内置的,定时任务工具存在。

    但是他们的一些让人掉头发的配置写法,以及增加运维心智负担,无法适应多实例部署场景等等原因,势必需要在 imi 框架中提供这个功能。

    设计

    imi 通过增加一个 CronProcess 进程用于定时任务的调度和执行,使用 Redis 作为数据存储。

    定时任务支持在以下进程中执行: Task 进程、Worker 进程,也支持新运行一个 Process 进程。

    支持设置某进程在当前实例/多实例中只运行一个。

    使用

    启用定时任务进程

    在项目 config.phpbeans 中加入:

    'AutoRunProcessManager'   =>  [
        'processes' =>  [
            'CronProcess',
        ],
    ],

    定义任务

    Task 任务

    与异步任务等同,不再赘述

    Process 任务

    与进程等同,不再赘述

    协程任务

    实现 Imi\Cron\Contract\ICronTask 接口、run() 方法

    定时规则

    支持注解设定和配置文件设定两种模式,其中配置文件设定,是可以覆盖注解设定的。

    注解设定

    注解 @Cron,类 Imi\Cron\Annotation\Cron

    @Cron(id="任务唯一ID", type="", year="", month="", day="", hour="", minute="", second="", unique=null, redisPool="", lockWaitTimeout="", maxExecutionTime="", force=false)

    属性
    id

    使用@Cron注解时的任务唯一ID。如果是 TaskProcess,默认使用 TaskProcess + 名称。

    type

    任务类型

    可选:

    random_worker-随机工作进程任务

    all_worker-所有工作进程执行的任务

    task-后台任务

    process-进程

    force

    每次启动服务强制执行,默认为false

    year

    指定任务执行年份,默认为 *

    * - 不限制

    2019 - 指定年

    2019-2022 - 指定年份区间

    2019,2021,2022 - 指定多个年份

    2n - 每 2 年,其它以此类推

    month

    指定任务执行月份,默认为 *

    * - 不限制

    1 (1 月), -1 (12 月) - 指定月份,支持负数为倒数的月

    1-6 (1-6 月), -3--1 (10-12 月) - 指定月份区间,支持负数为倒数的月

    1,3,5,-1 (1、3、5、12 月) - 指定多个月份,支持负数为倒数的月

    2n - 每 2 个月,其它以此类推

    day

    指定任务执行日期,默认为 *

    * - 不限制

    1 (1 日), -1 (每月最后一天) - 指定日期,支持负数为倒数的日期

    1-6 (1-6 日), -3--1 (每月倒数 3 天) - 指定日期区间,支持负数为倒数的日期

    1,3,5,-1 (每月 1、3、5、最后一天) - 指定多个日期,支持负数为倒数的日期

    2n - 每 2 天,其它以此类推

    year 1 (一年中的第 1 日), year -1 (每年最后一天) - 指定一年中的日期,支持负数为倒数的日期

    1-6 (一年中的第 1-6 日), -3--1 (每年倒数 3 天) - 指定一年中的日期区间,支持负数为倒数的日期

    year 1-6 (一年中的第 1-6 日), year -3--1 (每年倒数 3 天) - 指定一年中的日期区间,支持负数为倒数的日期

    1,3,5,-1 (每年 1、3、5、最后一天) - 指定一年中的多个日期,支持负数为倒数的日期

    year 1,3,5,-1 (每年 1、3、5、最后一天) - 指定一年中的多个日期,支持负数为倒数的日期

    week

    指定周几执行任务,默认为 *
    * - 不限制
    1 (周一), -1 (周日) - 指定周几(1-7),支持负数为倒数的周
    1-6 (周一到周六), -3--1 (周五到周日) - 指定周几,支持负数为倒数的周
    1,3,5,-1 (周一、三、五、日) - 指定多个日期,支持负数为倒数的周

    hour

    指定任务执行小时,默认为 *

    * - 不限制

    0 (0 点), -1 (23 点) - 指定小时,支持负数为倒数的小时

    1-6 (1-6 店), -3--1 (21-23 点) - 指定小时区间,支持负数为倒数的小时

    1,3,5,-1 (1、3、5、23 点) - 指定多个小时,支持负数为倒数的小时

    2n - 每 2 小时,其它以此类推

    minute

    指定任务执行分钟,默认为 *

    * - 不限制

    0 (0 分), -1 (23 分) - 指定分钟,支持负数为倒数的分钟

    1-6 (1-6 分), -3--1 (57-59 分) - 指定分钟区间,支持负数为倒数的分钟

    1,3,5,-1 (1、3、5、59 分) - 指定多个分钟,支持负数为倒数的分钟

    2n - 每 2 分钟,其它以此类推

    second

    指定任务执行秒,默认为 *

    * - 不限制

    0 (0 秒), -1 (23 秒) - 指定秒,支持负数为倒数的秒

    1-6 (1-6 秒), -3--1 (57-59 秒) - 指定秒区间,支持负数为倒数的秒

    1,3,5,-1 (1、3、5、59 秒) - 指定多个秒,支持负数为倒数的秒

    2n - 每 2 秒,其它以此类推

    unique

    定时任务唯一性设置
    当前实例唯一: current
    所有实例唯一: all
    不唯一: null

    redisPool

    用于锁的 Redis 连接池名

    lockWaitTimeout

    获取锁超时时间,单位:秒

    maxExecutionTime

    最大运行执行时间,单位:秒。

    该值与分布式锁超时时间共享,默认为 60 秒

    配置文件设定

    项目配置文件,beans 节中配置

    [
        'CronManager'   =>  [
            'tasks' =>  [
                // 任务唯一ID
                'taskName'  =>  [
                    // 任务类型,可选:worker-工作进程任务; task-任务; process-进程
                    'type'      =>  'worker',
                    // 任务执行回调,可以是callable类型,也可以是 task、process 名
                    'task'      =>  mixed,
                    // 定时配置
                    'cron'     =>  [
                        // 支持多个条件去触发
                        // 规则同 @Cron 注解
                        [
                            'year'  =>  '',
                            'month' =>  '',
                            'day'   =>  '',
                            'week'  =>  '',
                            'hour'  =>  '',
                            'minute'=>  '',
                            'second'=>  '',
                        ],
                    ],
                    // 可选配置
                    'data'              =>  null,
                    'unique'            =>  null,
                    'redisPool'         =>  'redis',
                    'lockWaitTimeout'   =>  10,
                    'maxExecutionTime'  =>  120,
                    'force'             =>  false,
                ],
            ],
        ],
    ]