隨着node的出現與發展,前端承擔了愈來愈多的職責。javascript
前端也有愈來愈多的場景須要使用批跑腳本html
切實的影響到業務,所以須要一套高可靠與及時告警的批跑管理系統。前端
本文將批跑管理的系統封裝爲一個npm模塊,能夠方便使用,而且提供一套簡單的web管理系統進行管理。java
1.安裝node
npm install schedule_task_monitor --save
gihub連接 https://github.com/WilsonLiu9...mysql
2.引入模塊並輸入參數linux
// init.js var { run, eventEmitter, app } = require('sche_task_monitor'); run({ mysql_config: { // mysql鏈接配置 host: 'localhost', port: '3306', user: 'root', password: '1234', database: 'db_lct_schedule', // 請先創建該數據庫 }, task_root_path: '/data/web/schedule/task/', // 任務腳本的根路徑 defaultRtx: 'wilsonsliu' // 告警默認傳送對象 }); // 啓動 node init.js
3.啓動web管理系統git
web系統在8017端口打開: http://127.0.0.1:8017github
node ./node_mudule/sche_task_monitor/webSystem/app.js
4.新建任務文件web
任務名稱爲test,此時須要可在/data/web/schedule/task/
新建一個test目錄,並新建/data/web/schedule/task/test/index.js
;
var fs = require('fs-extra'); var path = require('path'); console.log('測試啦') fs.writeFileSync(path.join(__dirname,'publish','a.txt'),'sdsds')
5.web系統新增任務
在web系統新增任務,例如以下配置
{ task_name: 'test', rule: '*/30 * * * * *', rtx_list: 'wilsonliuxyz@gmail.com;test@qq.com', // 告警時的相關責任人 title: '測試', description: '測試描述' }
此時,批跑管理系統將按照設定的任務規則運行,每15S進行一次。
模塊對外暴露了eventEmitter
,能夠經過監聽task_start,task_end,notify
事件來執行用戶相應的代碼。
eventEmitter.on('task_start', function ({ task_name, task_version }) {}); // 任務結束 eventEmitter.on('task_end', function ({ task_name, exit_code, task_version, error_log_list }) {}); // 監聽告警 eventEmitter.on('notify', function ({ title, content, task_name,notify_list }) {}); }
經過監聽notify
事件來實現本身的告警。用戶能夠自行選擇本身方便的方式,最好可以經過多類方式進行告警。例如微信,郵件,郵箱等等。達到高時效
notify
若是沒有task_name
,那麼notify_list
,則使用初始化傳入的defaultRtx
進行。
對於任務中生成的文件,規範放在對應的任務publish目錄。實現本身的發佈函數,在任務中進行調用。
任務正常退出 批跑模塊 會接受到 exit_code
爲0,由於異常退出會接收到 1。當退出碼爲非0值時,將觸發告警。用戶能夠經過process.exit(101)
,來觸發告警
task_name惟一,且能夠寫爲monitor/logline
的方式,則執行路徑變爲monitor/logline/index.js
。即入口文件爲拼接的方式可多層級。不建議過深,不方便管理與查看。
對於非node的批跑腳本,咱們能夠在入口文件中對其餘腳本再次進行調用的方式進行既能夠。
說到批跑,第一個想到的確定是利用linux自帶的crontab來完成定時批跑這一目的。
但依賴這種方式這樣存在如下問題,
做爲一個前端,固然是可以用JS實現的就所有就JS(node)來實現。
node自己有豐富的npm模塊,node-schedule
即是一個定時任務模塊,有4300+的star。
你能夠像crontab同樣,編輯定時的rule,在rule指定的時間,會執行相應的回調函數。
rule、timeout、last_start_time、last_end_time、last_warning_time
來實現任務的管理批跑系統的目的是爲了管理全部的批跑任務,而且對批跑任務進行監控。
同時,由於是會直接影響到線上的系統,因此在穩定性方面有高要求。
便利的基礎設施服務
task的入口腳本統一放在task目錄進行管理,而每一個任務的關鍵信息task_name、rule
等具體信息則錄入表t_task_list,進行管理。
如下示例中task_name
爲gold,則批跑系統去數據庫中找到task_name=gold
這一條記錄並按照,對應的rule
進行掛在定時器,gold/index.js
則爲對應的任務入口文件,系統經過node task/gold/index.js
執行特定任務。
src ├── index.js // 入口文件 ├── lib │ ├── execTask.js // 執行具體某個任務的代碼 │ ├── hook.js // 開始與結束任務的鉤子函數 │ ├── initDB.js // 初始化DB │ └── monitorHelper.js // 5個監控小助手 ├── webSystem // GUI的批跑管理系統 ├── task // 指定該目錄爲任務根目錄 | └── gold // 具體某一個定時任務 | └── index.js // 某一個任務的入口文件 | └—— logs // 本任務留下的日誌文件 │ └── 201711 // 某個月 │ ├── 23_213854.log // 按照 day_HHmmss構建目錄存放歷史版本 | └—— publish // 每次任務發佈的文件夾,發佈到線上須要手動調用發佈函數,任務退出後批跑系統會自動將本目錄下的文件備份到history目錄 | └—— history // 目錄下文件按照 gold_profit.201711231015.json 即 name + time(精確到分鐘) + 尾綴的形式保存 │ └── 201711 // 某一月份的歷史發佈文件 │ ├── 23_213854 // 按照 day_HHmmss構建目錄存放歷史版本 │ │ ├── currentYearPrice.json
child_process.spawn
子進程來運行任務,以保證批跑系統與具體任務之間進行隔離,任務的異常不會致使批跑系統的崩潰。經過利用child_process.spawn
的方式執行任務,規定task/task_name/index.js
爲任務的入口文件,至關於node task/task_name/index.js
。
優勢:
require
的方式進行引入,每次任務更新時不須要重啓批跑系統,只須要部署本身的任務的代碼文件便可須要注意的2點
批跑系統經過監放任務子進程的close事件,來了解任務是否執行完成。當exit_code爲非0值時,批跑系統將進行告警(關於process.exit
能夠閱讀文末的參考連接3)
exit_code=1
,catch
住異常後,可經過process.exit(exit_code)
來指定本身定義的exit_code
(100之內爲批跑系統保留狀態碼)利用開源的node-schedule
模塊,該模塊可完成相似crontab
的功能,而且支持crontab
的語法規則。主要用到scheduleJob
這個接口進行定時任務掛載。
系統啓動時,去數據庫的t_task_list
將全部任務的task_name、rule
數據取出,並遍歷進行掛載。同時,掛載後的句柄存儲在全局對象G_task_schedule_list
。
const schedule = require('node-schedule'); // 全局保存任務定時器的句柄 G_task_schedule_list G_task_schedule_list[task_name] = schedule.scheduleJob(rule, function () { // 回調函數中執行具體的任務 execTask(task_name, app); });
在如下5種狀況時,對任務相關責任人進行告警。
t_task_list
表中每一個任務可指定超時時間爲多少秒timeout
)exit_code
非0,即異常退出cron-parser
解析rule
獲得上次應該運行時間,經過與任務的last_start_time
比較肯定是否漏執行)G_task_schedule_list
與數據庫中任務進行比對,發現是否有任務被刪除)父進程經過監聽子進程的stdout,stderr
兩個輸出流,獲得子進程的日誌輸出。
日誌將會存放在task/logs/YYYYMM/DD/HHmmss.log
目錄下,按照任務執行的時間存放,同時將stderr
的信息入庫(爲保護批跑系統,作限制,只錄入前100條),用以在UI界面展現與告警時輸出。用戶若是須要詳細的日誌仍是須要查閱日誌文件。
stderr
能夠經過console.error
輸出,另外若是進程異常退出也會輸出到stderr,建議在catch住異常後經過console.error
進行輸出。
每次任務執行的時候,能夠將文件寫入到對應任務的的publish
目錄,若是須要發佈上線能夠手動調用Helper中的發佈函數,針對目前部分強耦合於其餘系統中的發佈功能,能夠以接口的形式批跑調用,並在接口中返回發佈的內容,任務再將其寫入publish
目錄以進行版本的備份。
每次任務退出後,批跑系統會檢測其publish
是否爲空,不爲空則移動到history
目錄目錄下,並以版本號爲文件夾存儲,以方便備份查看。
批跑系統掛載一個每3S執行一次的監控小助手,達到準實時監控的效果。
hook.js包含startExecTask, endExecTask兩個函數在任務開始結束時運行。
startExecTask 執行以下動做
task/task_name/publish
last_start_time,task_version
(任務的版本號根據運行時間生成const task_version = moment().format('YYYYMM/DD/HHmmss');
)t_task_exec_list
endExecTask執行以下動做
task/task_name/publish
到task/task_name/history/task_version
批跑系統做爲一個基礎設施與其餘系統最大的不一樣在於須要高穩定性且須要準確的監控告警以免任務出現各類狀況致使線上問題,卻後知後覺。
本系統的設計基本知足了設計目標,同時提供一套便於管理的web系統,能夠方便的進行任務的管理,與歷史執行狀況的查看。