原文鏈接: https://www.cnblogs.com/yalong/p/15601391.html
背景:
有個需求,需要每天刪除過期的數據,所以用到了定時任務,但是發現定時任務每次都是執行多次,原來是pm2 的 cluster模式導致的,最終還是解決了,在此記錄
一. 定時任務怎么寫
使用 node-schedule
, githuib地址是: https://github.com/node-schedule/node-schedule
node-schedule
更多使用可以參考這個https://www.cnblogs.com/zhongweiv/p/node_schedule.html
我的項目是koa2,這里以每3秒打印為例,具體使用就是在app.js 中添加如下代碼
const schedule = require("node-schedule");
const job = schedule.scheduleJob("*/3 * * * * *", function () {
console.log('每3秒我執行一次,啦啦啦' + new Date())
});
如下圖:
二.復現問題
1.使用pm2 的 cluster模式啟動服務
我的pm2 的配置文件,pm2.josn 內容如下:
{
"apps": [
{
"name": "koa-test",
"script": "bin/www",
"cwd": "",
"exec_mode": "cluster",
"instances": 0,
"autorestart": true,
"node_args": [],
"args": [],
"env": {
"NODE_ENV": "production"
}
}
]
}
執行 pm2 start ./pm2.json
啟動服務,如下圖
執行pm2 log
查看打印日志,如下圖
可以看到,每3秒后,一下子打印8次,就是說定時任務是重復執行的
三.解決問題
如下圖
可以看到 pm2 實例的id是不重復的, 那么在某個指定id下執行定時任務不就ok了
這個id的屬性獲取方式是 process.env.NODE_APP_INSTANCE
在項目中測試
const job = schedule.scheduleJob("*/3 * * * * *", function () {
console.log(process.env.NODE_APP_INSTANCE)
});
再查看pm2 log
就能看到打印的就是pm2 中每個 worker 的id值
最終代碼如下:
const job = schedule.scheduleJob("*/3 * * * * *", function () {
if (process.env.NODE_APP_INSTANCE === '0') {
console.log('每3秒我執行一次,啦啦啦' + new Date())
}
});
結果如下圖所示,問題得以解決
分析總結
定時任務重復執行的原因是pm2 的cluster 模式創建的每個worker進程,是同步執行的,所以就導致了重復執行,
Node.js—Cluster多進程模式與PM2的實現可以參考這里: https://www.cnblogs.com/xingchong/p/13183162.html