数据库动态配置定时任务

基于 Symfony 框架, 不同框架原理一样

数据表
1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE `task` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '任务ID task_id',
`name` varchar(32) NOT NULL COMMENT '任务名称',
`desc` varchar(255) NOT NULL DEFAULT '' COMMENT '任务描述',
`controller` varchar(255) NOT NULL COMMENT '控制器名称',
`action` varchar(255) NOT NULL COMMENT '操作名称',
`interval_time` int(11) unsigned NOT NULL COMMENT '间隔时间,单位:秒',
`last_execution_time` datetime DEFAULT NULL COMMENT '最后一次执行时间',
`log_path` varchar(255) NOT NULL COMMENT '日志路径',
`status` smallint(1) NOT NULL DEFAULT '0' COMMENT '状态 0:停止, 1:启用',
`generate_time` datetime NOT NULL COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='定时任务表';
Linux Crontab 或 Windows 计划任务 定时执行PHP文件(可创建多个相同任务)
1
*/1 * * * * /alidata/www/symfony/bin/TaskBatch.php >/dev/null 2>&1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

use AppBundle\Task\ProcessorTask;

require __DIR__.'/../vendor/autoload.php';
if (PHP_VERSION_ID < 70000) {
include_once __DIR__.'/../var/bootstrap.php.cache';
}

$kernel = new AppKernel('prod', false);
if (PHP_VERSION_ID < 70000) {
$kernel->loadClassCache();
}

$kernel->boot();
$task = new ProcessorTask($kernel->getContainer());
$task->run();
定时任务处理代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<?php

namespace AppBundle\Task;

use AppBundle\Entity\Task;
use AppBundle\Repository\TaskRepository;

class ProcessorTask extends BaseTask
{
/**
* Run Task.
*
* @throws \Exception
*/
public function run()
{
// 日志路径
$timedTaskLogPath = $this->getConfigParameter('system_timed_task_log_path');

try {
/** @var TaskRepository $taskRepository */
$taskRepository = $this->getRepository(Task::class);
// 定时任务列表,只查询 status = 1 的任务
$taskList = $taskRepository->getTaskList();

if (!empty($taskList)) {
// 增加内存,防止数据过大溢出
ini_set('memory_limit', '256M');
// 设置batch超时时间,避免数据过多处理超时
ini_set('max_execution_time', 1200);
// 当前时间
$nowTime = new \DateTime();

/** @var Task $task */
foreach ($taskList as $task) {
$taskLockFile = $timedTaskLogPath . 'task_' . $task->getId() . '.lock';
// 防止任务重复执行
if (file_exists($taskLockFile)) {
continue;
}

// 创建文件锁
file_put_contents($taskLockFile, $task->getId(), true);

$tmpTime = clone $nowTime;
$tmpTime->sub(new \DateInterval("PT{$task->getIntervalTime()}S"));
if (empty($task->getLastExecutionTime()) || !$task->getIntervalTime() || $tmpTime > $task->getLastExecutionTime()) {
$taskInstance = $this->get($task->getController());
$logPath = (string)$task->getLogPath();
if (!empty($logPath)) {
$logPath = $timedTaskLogPath . $logPath . '/';
}

// 执行任务
$taskInstance->{$task->getAction()}($task->getName(), $logPath);
// 更新任务执行时间
$taskRepository->saveEntity([
'lastExecutionTime' => new \DateTime(),
], $task);
}

// 解除文件锁
unlink($taskLockFile);
}
}
} catch (\Exception $e) {
$this->generateLog($e->getMessage(), $timedTaskLogPath);
}

exit;
}
}
0%