定时任务 | Crontab

Crontab / 定时任务

项目在线上运行时,经常要定时去执行某个功能(如:定时去远程拉取一些数据、定时计算数据库里的一些数据进行汇总),这时候就需要使用定时任务来处理了。

框架提供了二种方式执行定时任务,一种是在当前启动的子进程中执行,另一种是用一个新的进程执行(命令行执行)。

当前子进程中执行

有些定时任务是拉取一些数据放在内存中,供用户请求过程中使用,这种定时任务就希望在当前进程中调用(由于框架启动服务时是多进程架构,所以定时任务只会在子进程中执行,不会在主进程中执行),该功能是通过 think-crontab 模块来完成的。

配置

定时任务的配置文件为 src/config/crontab.js(多模块项目下配置文件为 src/common/config/crontab.js,也支持在每个模块下配置定时任务文件 src/[module]/config/crontab.js),配置项为一个数组。如:

module.exports = [{ interval: '10s', immediate: true, handle: () => { //do something } }, { cron: '0 */1 * * *', handle: 'crontab/test', type: 'all' }]

每个配置项支持的参数如下:

  • interval {String | Number} 执行的时间间隔 支持数字和字符串二种格式,单位是毫秒。如果是字符串,那么会用 think.ms 方法解析为数字。

调试

如果想看到定时任务是否在成功运行,可以通过 DEBUG=think-crontab npm start 启动项目查看打印的调试信息。

命令行执行

如果有些定时任务跨机房、跨机器只希望执行一次,或者定时任务比较耗时,那么可以通过命令行来执行。命令行执行需要结合系统的 crontab 任务来完成。

命令行执行直接通过自动脚本和路由地址即可,如:node production.js crontab/test,其中 crontab/test 为路由地址,这样结合系统的 crontab 就可以定时执行了。

通过命令 crontab -e 来编辑定时任务,如:

0 */1 * * * /bin/sh (cd projectpath; node production.js crontab/test) # 1 小时执行一次

常见问题

如何限制 Action 只能定时任务调用?

默认情况下,Action 不会限制哪些情况下才允许访问,这样定时任务对应的 Action 也可以通过输入 URL 来访问。但有时候我们并不希望这样,这时候可以通过 this.isCli 判断来阻止。如:

module.exports = class extends think.Controller { testAction() { // 如果不是定时任务调用,则拒绝 if(!this.isCli) return this.fail(1000, 'deny' ... } }

定时任务执行 Action 时并不是一个正常的用户请求,而是通过模拟一个请求来完成的,模拟时会将请求类型修改为 CLIisCli 就是通过判断请求类型是否为 CLI 来完成的。