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循環),直到追上當前時間。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM