使用说明
- 对于计划任务, 大部分时候我们依赖系统 通过CLI方式实现, 如: linux crontab
- 而一些情况下, 当需要动态生成异步并发操作时, 我们可以使用 "动态计划任务"
- 另一些情况下, 需要并发或失败重试操作时, 我们可以使用 "静态计划任务"
- 修复框架配置_of.com.timer.mode切换启动异步任务方式
动态计划任务 在代码执行时动态调用
of_base_com_timer::task($params, &$taskObj = null)
paramsarray
任务参数 { #动态任务, 未指定taskObj参数 "time" : 执行时间, 五年内秒数=xx后秒执行, 其它=指定时间 "call" : 框架标准的回调 接收 "自身" 数组做系统参数,可以修改其变量,如try,达到定时执行效果 "cNum" : 并发数量, 0=不设置, n=最大值, []=指定并发ID(最小值1) "try" : 尝试相隔秒数, 默认[], 如:[60, 100, ...] #单子任务, taskObj返回任务对象 "call" : 框架标准的回调 #多子任务, taskObj返回 {任务标识 : 任务对象, ...} "list" : 任务列表 {任务标识 : 框架回调结构, ...} "cNum" : 最大并行任务数量 }
&taskObj
任务对象, 指定时为任务模式, swoole环境下性能更高
<?php /** * 本函数内部会自动运行定时器, 如果定时器进程经常被系统杀死, * 可以在常用页面使用of_base_com_timer::timer()手动运行 * _of.com.timer 为计划任务的配置 * 如果 _of.com.timer.task.adapter 为 mysql, 需要下面的语句创建表, 也可以在 time 上做分区 * CREATE TABLE `_of_com_timer` ( * `hash` char(50) NOT NULL DEFAULT '' COMMENT '唯一标识符(十六进制时间戳+回调序列化的md5)', * `time` int(11) NOT NULL DEFAULT '0' COMMENT '执行时间戳', * `task` mediumtext NOT NULL COMMENT '存储调用数据{"call":回调结构,"try":尝试次数}', * PRIMARY KEY (`hash`), * KEY `根据时间查询执行范围` (`time`) USING BTREE * ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='框架计划任务存储列表'; */ of_base_com_timer::task(array( 'time' => 600, //十分钟后触发回调 'call' => array( 'asCall' => 'demo_index::index', //回调方法,返回 false 认为失败 'params' => array('自定义参数1') //自定义参数, ), 'cNum' => 3, //有且仅有3个并发一起执行 'try' => array( 100, //失败后100s重试 90 //再失败90s重试 ) ));
<?php /** * 获取回调任务返回信息 */ of_base_com_timer::task(array( 'call' => array( 'asCall' => 'demo_index::index', //回调方法,会回传返回值 'params' => array('自定义参数1') //自定义参数, ), ), $taskObj); /** * 描述 : 获取任务结果 * 参数 : * wait : 最大尝试时间(秒), 默认86400(24小时), 0=尝试一次 * 返回 : * false=任务运行中, true=任务中途退出(exit throw kill), array=任务正常返回 { * "result" : 任务返回的结果 * } */ var_dump($taskObj->result());
<?php /** * 获取回调任务返回信息 */ of_base_com_timer::task(array( 'list' => array( 'a' => array( 'asCall' => 'demo_index::index', 'params' => array('自定义参数1') ), 'b' => array( 'asCall' => 'demo_index::index', 'params' => array('自定义参数1') ) ), 'cNum' => 1 //最大同时执行list中的一个任务 ), $list); print_r($list); //{"a" : obj, "b" : obj} echo time(), "\n"; foreach ($list as $k => &$v) { var_dump($v->result()); echo time(), "\n"; }
静态计划任务 写在配置文件 "_of.com.timer.cron.path" 中指定的路径中
<?php /** * OF_URL/index.php?c=of_base_com_timer 激活计划任务 * call 与 try 参考 of_base_com_timer::task 动态计划任务 * time 参数 符合 linux crontab 语法定义, "* * * * *" 分 时 日 月 星期(0-6 0为星期日) * "* * * * *" 每1分钟执行一次 * "3,15 * * * *" 每小时的第3和第15分钟执行 * "3,15 8-11 * * *" 上午8点到11点的第3和第15分钟执行 * "3,15 8-11 */2 * *" 每隔两天的上午8点到11点的第3和第15分钟执行 * "3,15 8-11 * * 1" 每个星期一的上午8点到11点的第3和第15分钟执行 * "30 21 * * *" 每晚的21:30执行 * "45 4 1,10,22 * *" 每月1、10、22日的4:45执行 * "45 4 -1 * *" 负数为倒数, 每月最后一天的4:45执行 * "0 2 * * 6,0" 每周六、周日的2:00执行 * "* 2 * * 6,0" 每周六、周日的2:00-2:59每分钟执行一次 * "0 20-7/2 * * *" 晚上8点到早上7点之间, 每隔2小时执行 */ return array( array( //可以定义键值 'time' => '*/2 */5,1,*,14-30/3 * * 1', //符合 linux crontab 语法定义 'call' => array( 'asCall' => 'demo_ofControllers::cc', //回调方法,返回 false 认为失败 'params' => array('自定义参数1') //自定义参数, ), 'cNum' => 3, //有且仅有3个并发一起执行 'try' => array(60, 120, 300) ) );
计划任务回调 动态与静态计划任务回调结构统一
call方法接收的触发参数结构
{ "call" : 框架标准的回调, "time" : 执行时间, 时间戳, "cNum" : 并发数量, 0=不设置, n=最大并发 "try" : 尝试相隔秒数 "this" : { "cMd5" :o回调唯一值, 并发时存在 "cCid" :o并发ID, 从1开始, 并发时存在 "mark" :o数据回传标识, 存在时标识回传, 子任务存在 "type" : 任务类型, 1=定时器, 2=静态任务, 4=动态任务, 8=单子任务, 16=多子任务 } }
of_base_com_timer::data($data = true, $cIds = null, $call = null) 为并发提供共享数据
datanull bool array
读写数据, 仅可操作自身或未运行进程数据 null=不读数据, 仅关注运行状态使用 true=读取数据 false=清空读取, 读取数据后清空原始数据 数组=单层替换, 将数组键的值替换对应共享数据键的值
cIdsnull int bool array
指定任务中的并发ID null=读取自身 数字=指定并发ID 数组=多个并发ID, [并发ID, ...] true=正在运行 false=包括停止
callnull string array
指定任务ID null=读取自身 '/'开头字符串=指定任务ID 符合框架回调结构=指定任务的回调
返回
{ "info" : { 并发ID, 从小到大排序 : { "isRun" : 是否运行, true=运行, false=停止 "sort" : 在返回列表中的位置, 从0开始 "data" : 并发所存修改前的数据 }, ... }
//在并发回调方法中调用 print_r(of_base_com_timer::data()); //读取当前任务当前并发的存储数据 print_r(of_base_com_timer::data(null, true)); //读取当前任务运行并发的存储数据 print_r(of_base_com_timer::data(null, false)); //读取当前任务所有并发的存储数据 //假设通过 of_base_com_timer::info(1) 获取的任务ID为 $id print_r(of_base_com_timer::data(null, true, '/' . $id)); //读取指定任务运行并发的存储数据
of_base_com_timer::info($type) 获取当期运行的信息
typeint
读取类型(可叠加), 1=并发的任务, 2=分布定时器, 4=当前任务
<?php /** * type为1时 : 并发的任务 { * 任务ID : { * "call" : 统一回调结构 * "list" : 运行的任务列表 { * 并发ID : { * "datetime" : 任务启动时间 * "timestamp" : 任务启动时间戳 * } * } * } * } * type为2时 : 分布定时器 { * 节点名称 : {} * } * type为4时 : 获取当前任务, null=当前不在异步中, array={ * "task" : 同task任务参数 * "cArg" : 并发参数, 数组=启动并发 { * "cMd5" :o回调唯一值, 并发时存在 * "cCid" :o并发ID, 从1开始, 并发时存在 * "mark" :o数据回传标识, 存在时标识回传, 子任务存在 * "type" : 任务类型, 1=定时器, 2=静态任务, 4=动态任务, 8=单子任务, 16=多子任务 * } * } * type其它时 : 如1|2|4为7时 { * "concurrent" : type为1的结构, * "taskTrigger" : type为2的结构, * "nowTaskInfo" : type为4的结构 * } */ print_r(of_base_com_timer::info(7)); /** * 输出如下 : * Array * ( * [concurrent] => Array * ( * [305e58827000c31d7249a297790aa22f] => Array * ( * [call] => Array * ( * [0] => ctrl_index * [1] => asyn * ) * [list] => Array * ( * [1] => Array * ( * [datetime] => 2023-12-11 17:19:00 * [timestamp] => 1702286340 * ) * ) * ) * ) * [taskTrigger] => Array * ( * [da3c61c0c3bd31efcb4c17d5b2d754d5] => Array * ( * [time] => 1702286078 * ) * ) * [nowTaskInfo] => Array * ( * [call] => Array * ( * [time] => 1702286340 * [call] => Array * ( * [0] => ctrl_index * [1] => asyn * ) * [cNum] => Array * ( * [0] => 1 * ) * [try] => Array * ( * [0] => 60 * [1] => 120 * [2] => 300 * ) * ) * [cArg] => Array * ( * [cMd5] => 305e58827000c31d7249a297790aa22f * [cCid] => 1 * [type] => 2 * ) * ) * ) */
of_base_com_timer::renew($preg = true, $eTip = '') 判断已加载文件是否有更新
pregtrue string
忽略校验的正则, true=全校验, 字符串=以"@"开头的正则忽略路径
eTipstring
有更新时抛出错误, ""=不抛出, 字符串=抛出的错误信息
返回
true=有变动, false=未变动
二次开发
- 文件夹 /of/accy/com/timer 下存储着不同方式的异步任务对接文件
- 目前有已封装 default swoole
- 可以通过配置文件 _of.com.timer.fork.adapter 设置, 参考配置方式
- 开发更多的存储方式, 要实现以下方法
public static function fork($params) 启动异步任务
paramsarray
接收参数结构 { "asCall" : 回调方法, "params" : [ 自定义参数, {"type" : 任务类型(同计划任务回调结构中的"type"), ...} ] }