Egg 定時任務(wù)

2020-02-06 14:11 更新

const res = await ctx.curl('http://www.api.com/cache', {
dataType: 'json',
});
ctx.app.cache = res.data;
},
};

這個定時任務(wù)會在每一個 Worker 進(jìn)程上每 1 分鐘執(zhí)行一次,將遠(yuǎn)程數(shù)據(jù)請求回來掛載到 app.cache 上。

任務(wù)

  • task 或 subscribe 同時支持 generator function 和 async function。
  • task 的入?yún)?nbsp;ctx,匿名的 Context 實(shí)例,可以通過它調(diào)用 service 等。

定時方式

定時任務(wù)可以指定 interval 或者 cron 兩種不同的定時方式。

interval

通過 schedule.interval 參數(shù)來配置定時任務(wù)的執(zhí)行時機(jī),定時任務(wù)將會每間隔指定的時間執(zhí)行一次。interval 可以配置成

  • 數(shù)字類型,單位為毫秒數(shù),例如 5000。
  • 字符類型,會通過 ms 轉(zhuǎn)換成毫秒數(shù),例如 5s。
module.exports = {
schedule: {
// 每 10 秒執(zhí)行一次
interval: '10s',
},
};

cron

通過 schedule.cron 參數(shù)來配置定時任務(wù)的執(zhí)行時機(jī),定時任務(wù)將會按照 cron 表達(dá)式在特定的時間點(diǎn)執(zhí)行。cron 表達(dá)式通過 cron-parser 進(jìn)行解析。

注意:cron-parser 支持可選的秒(linux crontab 不支持)。

*    *    *    *    *    *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │ |
│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
│ │ │ │ └───── month (1 - 12)
│ │ │ └────────── day of month (1 - 31)
│ │ └─────────────── hour (0 - 23)
│ └──────────────────── minute (0 - 59)
└───────────────────────── second (0 - 59, optional)
module.exports = {
schedule: {
// 每三小時準(zhǔn)點(diǎn)執(zhí)行一次
cron: '0 0 */3 * * *',
},
};

類型

框架提供的定時任務(wù)默認(rèn)支持兩種類型,worker 和 all。worker 和 all 都支持上面的兩種定時方式,只是當(dāng)?shù)綀?zhí)行時機(jī)時,會執(zhí)行定時任務(wù)的 worker 不同:

  • worker 類型:每臺機(jī)器上只有一個 worker 會執(zhí)行這個定時任務(wù),每次執(zhí)行定時任務(wù)的 worker 的選擇是隨機(jī)的。
  • all 類型:每臺機(jī)器上的每個 worker 都會執(zhí)行這個定時任務(wù)。

其他參數(shù)

除了剛才介紹到的幾個參數(shù)之外,定時任務(wù)還支持這些參數(shù):

  • cronOptions: 配置 cron 的時區(qū)等,參見 cron-parser 文檔
  • immediate:配置了該參數(shù)為 true 時,這個定時任務(wù)會在應(yīng)用啟動并 ready 后立刻執(zhí)行一次這個定時任務(wù)。
  • disable:配置該參數(shù)為 true 時,這個定時任務(wù)不會被啟動。
  • env:數(shù)組,僅在指定的環(huán)境下才啟動該定時任務(wù)。

執(zhí)行日志

執(zhí)行日志會輸出到 ${appInfo.root}/logs/{app_name}/egg-schedule.log,默認(rèn)不會輸出到控制臺,可以通過 config.customLogger.scheduleLogger 來自定義。

// config/config.default.js
config.customLogger = {
scheduleLogger: {
// consoleLevel: 'NONE',
// file: path.join(appInfo.root, 'logs', appInfo.name, 'egg-schedule.log'),
},
};

動態(tài)配置定時任務(wù)

有時候我們需要配置定時任務(wù)的參數(shù)。定時任務(wù)還有支持另一種寫法:

module.exports = app => {
return {
schedule: {
interval: app.config.cacheTick,
type: 'all',
},
async task(ctx) {
const res = await ctx.curl('http://www.api.com/cache', {
contentType: 'json',
});
ctx.app.cache = res.data;
},
};
};

手動執(zhí)行定時任務(wù)

我們可以通過 app.runSchedule(schedulePath) 來運(yùn)行一個定時任務(wù)。app.runSchedule 接受一個定時任務(wù)文件路徑(app/schedule 目錄下的相對路徑或者完整的絕對路徑),執(zhí)行對應(yīng)的定時任務(wù),返回一個 Promise。

有一些場景我們可能需要手動的執(zhí)行定時任務(wù),例如

  • 通過手動執(zhí)行定時任務(wù)可以更優(yōu)雅的編寫對定時任務(wù)的單元測試。
const mm = require('egg-mock');
const assert = require('assert');

it('should schedule work fine', async () => {
const app = mm.app();
await app.ready();
await app.runSchedule('update_cache');
assert(app.cache);
});
  • 應(yīng)用啟動時,手動執(zhí)行定時任務(wù)進(jìn)行系統(tǒng)初始化,等初始化完畢后再啟動應(yīng)用。參見應(yīng)用啟動自定義章節(jié),我們可以在 app.js 中編寫初始化邏輯。
module.exports = app => {
app.beforeStart(async () => {
// 保證應(yīng)用啟動監(jiān)聽端口前數(shù)據(jù)已經(jīng)準(zhǔn)備好了
// 后續(xù)數(shù)據(jù)的更新由定時任務(wù)自動觸發(fā)
await app.runSchedule('update_cache');
});
};

擴(kuò)展定時任務(wù)類型

默認(rèn)框架提供的定時任務(wù)只支持每臺機(jī)器的單個進(jìn)程執(zhí)行和全部進(jìn)程執(zhí)行,有些情況下,我們的服務(wù)并不是單機(jī)部署的,這時候可能有一個集群的某一個進(jìn)程執(zhí)行一個定時任務(wù)的需求。

框架并沒有直接提供此功能,但開發(fā)者可以在上層框架自行擴(kuò)展新的定時任務(wù)類型。

在 agent.js 中繼承 agent.ScheduleStrategy,然后通過 agent.schedule.use() 注冊即可:

module.exports = agent => {
class ClusterStrategy extends agent.ScheduleStrategy {
start() {
// 訂閱其他的分布式調(diào)度服務(wù)發(fā)送的消息,收到消息后讓一個進(jìn)程執(zhí)行定時任務(wù)
// 用戶在定時任務(wù)的 schedule 配置中來配置分布式調(diào)度的場景(scene)
agent.mq.subscribe(schedule.scene, () => this.sendOne());
}
}
agent.schedule.use('cluster', ClusterStrategy);
};

ScheduleStrategy 基類提供了:

  • schedule - 定時任務(wù)的屬性,disable 是默認(rèn)統(tǒng)一支持的,其他配置可以自行解析。
  • this.sendOne(...args) - 隨機(jī)通知一個 worker 執(zhí)行 task,args 會傳遞給 subscribe(...args) 或 task(ctx, ...args)。
  • this.sendAll(...args) - 通知所有的 worker 執(zhí)行 task。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號