zoukankan      html  css  js  c++  java
  • egg定时任务原理

    在egg定时任务里增加多一种类型, 用在多pod集群下, 定时任务只跑一遍。

    虽然我觉得这个功能完全可以放在项目业务自己实现, 不用集成进内部框架, 但还是去看了一下, 正好想了解一下egg的定时任务是怎么做的。

    egg-schedule

    这是egg用到的定时任务插件, 源码看起来不难, 花了点时间在时间调度的逻辑。关键在三个函数。

    start() {
    
    ​    /* istanbul ignore next */if (this.agent.schedule.closed) return;
    
    ​    if (this.schedule.immediate) {
    
    ​      this.logger.info(`[Timer] ${this.key} next time will execute immediate`);
    
    ​      setImmediate(() => this.handler());
    
    ​    } else {
    
    ​      this._scheduleNext();
    
    ​    }
    
      }

    首先, 如果是设置了immediate, 则调用node自身的setImmediate方法。

    如果不是,则过入_scheduleNext函数。

    _scheduleNext() {
      /* istanbul ignore next */
      if (this.agent.schedule.closed) return;
    
      // get next tick
      const nextTick = this.getNextTick();
    
      if (nextTick) {
        this.logger.info(`[Timer] ${this.key} next time will execute after ${nextTick}ms at ${utility.logDate(new Date(Date.now() + nextTick))}`);
        this.safeTimeout(() => this.handler(), nextTick);
      } else {
        this.logger.info(`[Timer] ${this.key} reach endDate, will stop`);
      }
    }

    从这里可以大概看出, 获取任务的下一个执行时间, 然后调用setTimeout方法, 还是node自身的。这里有一点, 之所以要用safe-timeout库, 是因为node自身的setTimeout函数设置的时间间隔是一个32位的整数, 换算成时间, 只能存从之后24天的时间, 如果大于24天, 可能就会溢出, 达不到想要的定时效果。

    接下来, 就是看怎样获取定时任务的下次执行时间。答案在getNextTick函数。

    getNextTick() {
    
    ​    // interval-style
    if (this.schedule.interval) return ms(this.schedule.interval);
    
    ​    // cron-style
    if (this[CRON_INSTANCE]) {
    
    ​      // calculate next cron tick
    
    ​      const now = Date.now();
    
    ​      let nextTick;
    
    ​      let nextInterval;
    
    ​      // loop to find next feature time
    do {
    
    ​        try {
    
    ​          nextInterval = this[CRON_INSTANCE].next();
    
    ​          nextTick = nextInterval.getTime();
    
    ​        } catch (err) {
    
    ​          // Error: Out of the timespan range
    return;
    
    ​        }
    
    ​      } while (now >= nextTick);
    
    ​      return nextTick - now;
    
    ​    }
    
      }

    如果是间隔(interval), 直接返回秒数;

    如果是cron, 拿到下次定时的时间, 再与当前时间比较:

    如果下次定时时间大于当前时间, 说明任务还没到执行时间, 返回下次定时时间与当前时间的差值, 作为setTimeout的参数;

    如果下次定时时间小于当前时间, 则让下次定单时间一直追上当前时间(while循环),直到追上当前时间。

     

  • 相关阅读:
    监督学习
    第一个应用:鸢尾花分类
    第一章 计算机系统漫游
    前言
    python批量下载验证码,用来做验证码处理
    windows下安装tesserocr
    python 爬虫之requests爬取页面图片的url,并将图片下载到本地
    electron实现透明点投的方法
    css之实现下拉框自上而下展开动画效果&&自下而上收起动画效果
    react项目中canvas之画形状(圆形,椭圆形,方形)
  • 原文地址:https://www.cnblogs.com/cool-fire/p/12455134.html
Copyright © 2011-2022 走看看