Become a sponsor

定时任务
定时任务模块基于 APScheduler 实现,支持 Cron 表达式调度、任务执行日志、动态启停等功能。包含 job(任务定义)、job_log(执行日志)两个子模块。
application/job/
├── models.py # 任务模型
├── forms.py # 表单验证
├── services.py # 业务逻辑层
├── views.py # 视图层
└── urls.py # 路由配置
application/job_log/
├── models.py # 执行日志模型
├── services.py # 日志业务逻辑
└── urls.py # 路由配置# application/job/models.py
from application.models import BaseModel
class Job(BaseModel):
"""定时任务模型类"""
class Meta:
db_table = 'django_job'
job_name = models.CharField(max_length=255, verbose_name='任务名称')
job_alias = models.CharField(max_length=255, null=True, blank=True, verbose_name='任务别名')
job_group = models.CharField(max_length=255, null=True, blank=True, verbose_name='任务分组')
job_trigger = models.CharField(max_length=255, null=True, blank=True, verbose_name='任务触发器')
status = models.IntegerField(default=0, verbose_name='任务状态:0-未发布 1-运行中 2-暂停 3-删除')
cron_expression = models.CharField(max_length=255, null=True, blank=True, verbose_name='Cron表达式')
execute_policy = models.IntegerField(default=1, verbose_name='执行策略:1-立即执行 2-执行一次 3-放弃执行')
is_sync = models.IntegerField(default=0, verbose_name='是否同步任务:0-否 1-是')
url = models.CharField(max_length=255, null=True, blank=True, verbose_name='任务URL')
params = models.TextField(null=True, blank=True, verbose_name='任务参数')
note = models.CharField(max_length=255, null=True, blank=True, verbose_name='任务备注')| 字段 | 类型 | 说明 |
|---|---|---|
job_name | str | 任务名称(唯一标识) |
job_alias | str | 任务别名(显示用) |
job_group | str | 任务分组(如"系统任务"、"业务任务") |
job_trigger | str | 触发器类型(cron/interval/date) |
status | int | 状态:0-未发布 1-运行中 2-暂停 3-删除 |
cron_expression | str | Cron 表达式 |
execute_policy | int | 执行策略:1-立即执行 2-执行一次 3-放弃执行 |
is_sync | int | 是否同步:0-异步 1-同步 |
url | str | 任务执行的 URL |
params | str | 任务参数(JSON 格式) |
# application/job_log/models.py
from application.models import BaseModel
class JobLog(BaseModel):
"""定时任务日志模型类"""
class Meta:
db_table = 'django_job_log'
job_id = models.IntegerField(default=0, verbose_name='任务ID')
job_name = models.CharField(max_length=255, verbose_name='任务名称')
job_group = models.CharField(max_length=255, null=True, blank=True, verbose_name='任务分组')
job_trigger = models.CharField(max_length=255, null=True, blank=True, verbose_name='任务触发器')
job_message = models.CharField(max_length=500, null=True, blank=True, verbose_name='任务日志信息')
cron_expression = models.CharField(max_length=255, null=True, blank=True, verbose_name='Cron表达式')
status = models.IntegerField(default=0, verbose_name='执行状态:0-正常 1-失败')
start_time = models.DateTimeField(null=True, blank=True, verbose_name='执行开始时间')
end_time = models.DateTimeField(null=True, blank=True, verbose_name='执行结束时间')
consume_time = models.BigIntegerField(default=0, verbose_name='执行耗时(毫秒)')
exception_info = models.TextField(null=True, blank=True, verbose_name='异常信息')| 字段 | 允许值 | 允许的特殊字符 |
|---|---|---|
| 秒 | 0-59 | , - * / |
| 分 | 0-59 | , - * / |
| 时 | 0-23 | , - * / |
| 日 | 1-31 | , - * / |
| 月 | 1-12 | , - * / |
| 周 | 0-7 | , - * / |
0 0/5 * * * ? 每5分钟执行
0 0 2 * * ? 每天凌晨2点执行
0 0 0 1 * ? 每月1号零点执行
0 0 * * * ? 每小时执行
0 0 9 * * 1-5 工作日上午9点执行
0 0/30 8-18 * * ? 工作时间每30分钟执行| 字符 | 说明 | 示例 |
|---|---|---|
* | 所有值 | * * * * * 每分钟 |
? | 不指定值(日和周) | 0 0 12 * * ? |
- | 范围 | 1-5 表示 1 到 5 |
, | 列表 | 1,3,5 表示 1、3、5 |
/ | 步长 | 0/5 从 0 开始每 5 |
未发布(0) → 运行中(1) → 暂停(2) → 运行中(1) → 删除(3)
↓
删除(3)| 状态 | 说明 | 可执行操作 |
|---|---|---|
| 0-未发布 | 任务已创建但未启动 | 启动、编辑、删除 |
| 1-运行中 | 任务正在调度执行 | 暂停、立即执行、编辑 |
| 2-暂停 | 任务已暂停 | 恢复、编辑、删除 |
| 3-删除 | 任务已删除(逻辑删除) | 无 |
| 策略 | 说明 | 场景 |
|---|---|---|
| 1-立即执行 | 错过执行时间后立即补执行 | 关键任务(如数据备份) |
| 2-执行一次 | 错过执行时间后只执行一次 | 普通任务 |
| 3-放弃执行 | 错过执行时间后放弃本次执行 | 非关键任务 |
| 接口 | 方法 | 权限节点 | 说明 |
|---|---|---|---|
/job/page | GET | sys:job:page | 任务分页列表 |
/job/detail/<int:id> | GET | sys:job:detail | 任务详情 |
/job/add | POST | sys:job:add | 新增任务 |
/job/update | PUT | sys:job:update | 编辑任务 |
/job/delete/<int:id> | DELETE | sys:job:delete | 删除任务 |
/job/status | PUT | sys:job:status | 启停任务 |
/job/run | POST | sys:job:run | 立即执行 |
/job/log/page | GET | sys:jobLog:page | 执行日志 |
多实例部署时,定时任务可能重复执行。项目通过 Redis 分布式锁解决:
1. 任务触发时,先尝试获取 Redis 锁
2. 获取成功 → 执行任务 → 释放锁
3. 获取失败 → 跳过本次执行(其他实例正在执行)锁的 Key
分布式锁的 Key 格式为 job:lock:{job_id},TTL 与任务执行超时时间一致。
定时任务模块具备以下特点:
1. APScheduler:基于成熟的调度框架,支持 Cron 表达式
2. 动态管理:通过接口动态添加、修改、启停任务
3. 执行日志:自动记录每次执行的开始时间、耗时、状态、异常
4. 并发控制:可配置是否允许并发执行
5. 错过策略:配置错过执行时的处理策略
6. 分布式锁:多实例部署时避免任务重复执行
7. 立即执行:支持手动触发任务立即执行