• nodejs定时任务


    项目需求:

    1. 每5秒执行一次,多个定时任务错开,即cron表达式中斜杆前带数字,例如 ‘1/5 * * * * *’
    2. 定时任务准时,延误低

    搜索了nodejs的定时任务,其实不多,找到了以下三个常用的:

    • node-cron
    • node-schedule
    • cron

    1 node-cron

    示例代码

    const nodeCron = require('node-cron');
    // 每5秒执行一次
    const cron = '*/5 * * * * *';
    // 自带验证cron的有效性
    const valid = nodeCron.validate(cron)
    if(!valid) {
        console.log(cron,' ===> Cron 无效');
        return;
    }
    nodeCron.schedule(cron, () => {
        console.log(dayjs().format('HH:mm:ss'))
        // todo: do task
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    优点:运行稳定,自带校验方法 validate
    缺点:cron表达式不支持斜杆前面带数字,例如从第2秒开始每5秒执行一次,即 ‘2/5 * * * * *’

    2 node-schedule

    最早用了 node-schedule
    每天定时截图然后自动发送邮件,以达到自动巡检的目的,每天一次,已经运行2年了,没什么问题。

    示例代码:

    const nodeSchedule= require('node-schedule')
    // 工作日的8:55:00
    const rule = {hour:8, minute:55, second:0, dayOfWeek:[1,2,3,4,5]};
    nodeSchedule.scheduleJob(rule, async () => {
        const res = await doScreenshot();
      })
      
    // 截图任务
    const doScreenshot = ()=>{
      // todo: return new Promise...
    }
    
    // 当进程退出时优雅结束任务
    process.on('SIGINT', function () {
        console.log('========= SIGINT')
        nodeSchedule.gracefulShutdown().then(() => process.exit(0))
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    然而,在另外一个项目里面使用了cron表达式,在执行较为复杂的任务时,发现偶发在某个整点里面触发2次

    // 每5秒执行一次
    const cron = '*/5 * * * * *';
    nodeSchedule.scheduleJob(cron,()=>{
        console.log(dayjs().format('HH:mm:ss'))
        // todo: do task
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    优点:支持cron表达式斜杆前面带数字,弥补了 node-cron 缺点,自带优雅结束所有任务方法,rule规则还支持对象文本语法
    缺点:当使用cron表达式,频繁执行复杂任务时,任务时间会出现错乱,整点还会偶发触发2次,比较适合时间间隔比较大的而无阻塞的任务

    3 cron

    最后选择这个,刚好满足项目需求。

    示例代码

    const CronJob = require('cron').CronJob;
    const validator = require('cron-validator')
    
    const createCronJob = (cron) => {
        const isValid = validator.isValidCron(cron, { seconds: true, allowBlankDay: true, alias: true, allowSevenAsSunday: true })
        if (!isValid) {
            console.log(cron, ' ===> Cron 无效');
            return;
        }
        
    	const job = new CronJob(
    	    cron.replace('?', '*'),  // 不支持问号,则将cron的问号转成*
    	    function () {
    	        console.log(dayjs().format('HH:mm:ss'))
    	        // todo: do task
    	    },
    	    (e) => { console.log('complete ', e) },
    	    true,
    	    'Asia/Shanghai'
    	);
    	console.log('job cron: ',job.cronTime.source)
    	return job;
    }
    
    createCronJob('*/5 * * * * *')
    
    • 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

    示例代码里面增加了一个’cron-validator’ 用来做cron校验。

    优点:支持cron表达式斜杆前面带数字,弥补了 node-cron 缺点
    缺点:不支持最后一位的问号,不过可以将问号替换为星号

    最后选择了cron,目前运行稳定

    最后附上通配符解释
    在这里插入图片描述

    如果只有5位,则是省略了秒,即第一位表示分钟
    如果有6位,则第一位表示秒
    也有7位的,最后一位表示年

  • 相关阅读:
    ES的索引结构与算法解析
    60 个深度学习教程:包含论文、实现和注释 | 开源日报 No.202
    2023年数维杯数学建模B题节能列车运行控制优化策略求解全过程文档及程序
    10.23 校招 实习 内推 面经
    GPT-4并非世界模型,LeCun双手赞同!ACL力证LLM无法模拟真实世界
    新零售SaaS架构:中央库存系统架构设计
    NAT地址转换,路由器作为出口设备,实现负载分担
    shell脚本入门-多命令处理与变量
    Eureka 注册中心
    8.11 DAy39---MyBatis面试题
  • 原文地址:https://blog.csdn.net/geol200709/article/details/133127718