码迷,mamicode.com
首页 > 其他好文 > 详细

egg定时任务原理

时间:2020-03-10 14:11:04      阅读:88      评论:0      收藏:0      [点我收藏+]

标签:and   mamicode   key   closed   种类   ext   pre   一个   time()   

在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循环),直到追上当前时间。

 

egg定时任务原理

标签:and   mamicode   key   closed   种类   ext   pre   一个   time()   

原文地址:https://www.cnblogs.com/cool-fire/p/12455134.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!