摘要:任務退出碼任務正常退出批跑模塊會接受到為,因為異常退出會接收到。主要注意的檢查項為連接未關閉等。每次任務退出后,批跑系統(tǒng)會檢測其是否為空,不為空則移動到目錄目錄下,并以版本號為文件夾存儲,以方便備份查看。
背景
隨著node的出現(xiàn)與發(fā)展,前端承擔了越來越多的職責。
前端也有越來越多的場景需要使用批跑腳本
利用爬蟲或者接口定時同步數(shù)據(jù)到DB
線上配置文件、數(shù)據(jù)文件定時批跑生成并發(fā)布到線上
切實的影響到業(yè)務,因此需要一套高可靠與及時告警的批跑管理系統(tǒng)。
本文將批跑管理的系統(tǒng)封裝為一個npm模塊,可以方便使用,并且提供一套簡單的web管理系統(tǒng)進行管理。
如何使用1.安裝
npm install schedule_task_monitor --save
gihub鏈接 https://github.com/WilsonLiu9...
2.引入模塊并輸入?yún)?shù)
// 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", // 請先建立該數(shù)據(jù)庫 }, task_root_path: "/data/web/schedule/task/", // 任務腳本的根路徑 defaultRtx: "wilsonsliu" // 告警默認傳送對象 }); // 啟動 node init.js
3.啟動web管理系統(tǒng)
web系統(tǒng)在8017端口打開: http://127.0.0.1:8017
node ./node_mudule/sche_task_monitor/webSystem/app.js
4.新建任務文件
任務名稱為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系統(tǒng)新增任務
在web系統(tǒng)新增任務,例如如下配置
{ task_name: "test", rule: "*/30 * * * * *", rtx_list: "[email protected];[email protected]", // 告警時的相關責任人 title: "測試", description: "測試描述" }
此時,批跑管理系統(tǒng)將按照設定的任務規(guī)則運行,每15S進行一次。
事件系統(tǒng)模塊對外暴露了eventEmitter,可以通過監(jiān)聽task_start,task_end,notify事件來執(zhí)行用戶相應的代碼。
eventEmitter.on("task_start", function ({ task_name, task_version }) {}); // 任務結束 eventEmitter.on("task_end", function ({ task_name, exit_code, task_version, error_log_list }) {}); // 監(jiān)聽告警 eventEmitter.on("notify", function ({ title, content, task_name,notify_list }) {}); }注意的點 告警模塊需要自己設計
通過監(jiān)聽notify事件來實現(xiàn)自己的告警。用戶可以自行選擇自己方便的方式,最好能夠通過多類方式進行告警。例如微信,郵件,郵箱等等。達到高時效
notify如果沒有task_name,那么notify_list,則使用初始化傳入的defaultRtx進行。
發(fā)布批跑生成的文件對于任務中生成的文件,規(guī)范放在對應的任務publish目錄。實現(xiàn)自己的發(fā)布函數(shù),在任務中進行調用。
任務退出碼 exit_code任務正常退出 批跑模塊 會接受到 exit_code 為0,因為異常退出會接收到 1。當退出碼為非0值時,將觸發(fā)告警。用戶可以通過process.exit(101),來觸發(fā)告警
task_name設計task_name唯一,且可以寫為monitor/logline的方式,則執(zhí)行路徑變?yōu)?b>monitor/logline/index.js。即入口文件為拼接的方式可多層級。不建議過深,不方便管理與查看。
非node批跑腳本?對于非node的批跑腳本,我們可以在入口文件中對其他腳本再次進行調用的方式進行既可以。
系統(tǒng)設計一覽 定方向 利用crontab說到批跑,第一個想到的肯定是利用linux自帶的crontab來完成定時批跑這一目的。
但依賴這種方式這樣存在以下問題,
每個任務都需要自行去crontab去新增一條規(guī)則,久而久之難以維護
任務執(zhí)行的各種告警實現(xiàn)困難,漏執(zhí)行,超時,異常退出等等
利用node開源的模塊node-schedule作為一個前端,當然是能夠用JS實現(xiàn)的就全部就JS(node)來實現(xiàn)。
node本身有豐富的npm模塊,node-schedule便是一個定時任務模塊,有4300+的star。
你可以像crontab一樣,編輯定時的rule,在rule指定的時間,會執(zhí)行相應的回調函數(shù)。
通過表t_task_list來進行管理任務,主要錄入每個任務的rule、timeout、last_start_time、last_end_time、last_warning_time來實現(xiàn)任務的管理
通過批跑系統(tǒng)統(tǒng)一對任務管理與監(jiān)控,以便對各種任務進行告警
定目標批跑系統(tǒng)的目的是為了管理所有的批跑任務,并且對批跑任務進行監(jiān)控。
同時,因為是會直接影響到線上的系統(tǒng),所以在穩(wěn)定性方面有高要求。
高穩(wěn)定性
弱侵入性(盡量減少批跑系統(tǒng)對相應任務的侵入)
便利的基礎設施服務
定時運行
各種異常情形下進行告警
日志輸出
版本備份
任務執(zhí)行數(shù)據(jù)入庫與統(tǒng)計
定規(guī)范task的入口腳本統(tǒng)一放在task目錄進行管理,而每個任務的關鍵信息task_name、rule等具體信息則錄入表t_task_list,進行管理。
以下示例中task_name為gold,則批跑系統(tǒng)去數(shù)據(jù)庫中找到task_name=gold這一條記錄并按照,對應的rule進行掛在定時器,gold/index.js則為對應的任務入口文件,系統(tǒng)通過node task/gold/index.js執(zhí)行特定任務。
src ├── index.js // 入口文件 ├── lib │ ├── execTask.js // 執(zhí)行具體某個任務的代碼 │ ├── hook.js // 開始與結束任務的鉤子函數(shù) │ ├── initDB.js // 初始化DB │ └── monitorHelper.js // 5個監(jiān)控小助手 ├── webSystem // GUI的批跑管理系統(tǒng) ├── task // 指定該目錄為任務根目錄 | └── gold // 具體某一個定時任務 | └── index.js // 某一個任務的入口文件 | └—— logs // 本任務留下的日志文件 │ └── 201711 // 某個月 │ ├── 23_213854.log // 按照 day_HHmmss構建目錄存放歷史版本 | └—— publish // 每次任務發(fā)布的文件夾,發(fā)布到線上需要手動調用發(fā)布函數(shù),任務退出后批跑系統(tǒng)會自動將本目錄下的文件備份到history目錄 | └—— history // 目錄下文件按照 gold_profit.201711231015.json 即 name + time(精確到分鐘) + 尾綴的形式保存 │ └── 201711 // 某一月份的歷史發(fā)布文件 │ ├── 23_213854 // 按照 day_HHmmss構建目錄存放歷史版本 │ │ ├── currentYearPrice.jsonweb管理端展示
模塊化、簡單化。通過批跑系統(tǒng)模塊化,并保證每個模塊代碼精簡與健壯,以此來提高批跑系統(tǒng)的穩(wěn)定性。
批跑系統(tǒng)與任務隔離。批跑系統(tǒng)通過child_process.spawn子進程來運行任務,以保證批跑系統(tǒng)與具體任務之間進行隔離,任務的異常不會導致批跑系統(tǒng)的崩潰。
兜底,pm2管理。任何系統(tǒng)都難以避免掛掉,如果系統(tǒng)掛掉則通過PM2自動重啟任務。
弱侵入性通過利用child_process.spawn的方式執(zhí)行任務,規(guī)定task/task_name/index.js為任務的入口文件,相當于node task/task_name/index.js。
優(yōu)點:
批跑腳本任務代碼無需做任何改造,可以選擇自己喜歡的方式去編寫代碼。
非通過require的方式進行引入,每次任務更新時不需要重啟批跑系統(tǒng),只需要部署自己的任務的代碼文件即可
需要注意的2點
任務不可以一直掛起,任務執(zhí)行完成需退出。主要注意的檢查項為mysql連接未關閉等。
批跑系統(tǒng)通過監(jiān)聽任務子進程的close事件,來了解任務是否執(zhí)行完成。當exit_code為非0值時,批跑系統(tǒng)將進行告警(關于process.exit可以閱讀文末的參考鏈接3)
未catch住的異常導致的退出將會吐出exit_code=1,catch住異常后,可通過process.exit(exit_code)來指定自己定義的exit_code(100以內為批跑系統(tǒng)保留狀態(tài)碼)
子任務正常執(zhí)行會吐出0
便利的基礎設施服務 定時運行利用開源的node-schedule模塊,該模塊可完成類似crontab的功能,并且支持crontab的語法規(guī)則。主要用到scheduleJob這個接口進行定時任務掛載。
系統(tǒng)啟動時,去數(shù)據(jù)庫的t_task_list將所有任務的task_name、rule數(shù)據(jù)取出,并遍歷進行掛載。同時,掛載后的句柄存儲在全局對象G_task_schedule_list。
const schedule = require("node-schedule"); // 全局保存任務定時器的句柄 G_task_schedule_list G_task_schedule_list[task_name] = schedule.scheduleJob(rule, function () { // 回調函數(shù)中執(zhí)行具體的任務 execTask(task_name, app); });各種異常情形下進行告警
在以下5種情況時,對任務相關責任人進行告警。
任務執(zhí)行超時告警(t_task_list表中每個任務可指定超時時間為多少秒timeout)
exit_code非0,即異常退出
漏執(zhí)行告警(cron-parser解析rule得到上次應該運行時間,通過與任務的last_start_time比較確定是否漏執(zhí)行)
數(shù)據(jù)庫中任務被刪除通知(通過將目前掛載的任務G_task_schedule_list與數(shù)據(jù)庫中任務進行比對,發(fā)現(xiàn)是否有任務被刪除)
批跑模塊內部異常
日志輸出父進程通過監(jiān)聽子進程的stdout,stderr兩個輸出流,得到子進程的日志輸出。
日志將會存放在task/logs/YYYYMM/DD/HHmmss.log目錄下,按照任務執(zhí)行的時間存放,同時將stderr的信息入庫(為保護批跑系統(tǒng),做限制,只錄入前100條),用以在UI界面展示與告警時輸出。用戶如果需要詳細的日志還是需要查閱日志文件。
stderr可以通過console.error輸出,另外如果進程異常退出也會輸出到stderr,建議在catch住異常后通過console.error進行輸出。
版本備份每次任務執(zhí)行的時候,可以將文件寫入到對應任務的的publish目錄,如果需要發(fā)布上線可以手動調用Helper中的發(fā)布函數(shù),針對目前部分強耦合于其他系統(tǒng)中的發(fā)布功能,可以以接口的形式批跑調用,并在接口中返回發(fā)布的內容,任務再將其寫入publish目錄以進行版本的備份。
每次任務退出后,批跑系統(tǒng)會檢測其publish是否為空,不為空則移動到history目錄目錄下,并以版本號為文件夾存儲,以方便備份查看。
監(jiān)控小助手批跑系統(tǒng)掛載一個每3S執(zhí)行一次的監(jiān)控小助手,達到準實時監(jiān)控的效果。
小助手1:已存在的任務:數(shù)據(jù)庫更新rule,cancel定時任務 并設置掛載新規(guī)則的定時任務;新增任務:按照rule進行掛載
小助手2:用戶設置task_status為2,則殺死當前進程
小助手3:根據(jù)數(shù)據(jù)庫中的timeout字段,進行超時提醒
小助手4:任務漏執(zhí)行,告警通知
小助手5:任務在數(shù)據(jù)庫中被刪除告警用戶
任務的初始化與結束hook.js包含startExecTask, endExecTask兩個函數(shù)在任務開始結束時運行。
startExecTask 執(zhí)行如下動作
置空任務的發(fā)布文件夾 task/task_name/publish
更新任務表中的last_start_time,task_version(任務的版本號根據(jù)運行時間生成const task_version = moment().format("YYYYMM/DD/HHmmss");)
插入一條任務執(zhí)行記錄到t_task_exec_list
endExecTask執(zhí)行如下動作
設置退出的事件與退出碼
版本備份 :備份本次執(zhí)行的發(fā)布文件夾task/task_name/publish到task/task_name/history/task_version
更新任務運行記錄(包括錄入logs、發(fā)布的文件路徑數(shù)組)
小結批跑系統(tǒng)作為一個基礎設施與其他系統(tǒng)最大的不同在于需要高穩(wěn)定性且需要準確的監(jiān)控告警以避免任務出現(xiàn)各種情況導致線上問題,卻后知后覺。
本系統(tǒng)的設計基本滿足了設計目標,同時提供一套便于管理的web系統(tǒng),可以方便的進行任務的管理,與歷史執(zhí)行情況的查看。
參考資料node-schedule
解析crontab的rule規(guī)則 cron-parser
process對象與exit_code
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/94177.html
摘要:延伸閱讀學習與實踐資料索引與前端工程化實踐前端每周清單半年盤點之篇前端每周清單半年盤點之與篇前端每周清單半年盤點之篇 前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點;分為新聞熱點、開發(fā)教程、工程實踐、深度閱讀、開源項目、巔峰人生等欄目。歡迎關注【前端之巔】微信公眾號(ID:frontshow),及時獲取前端每周清單;本文則是對于半年來發(fā)布的前端每周清單...
摘要:廣義的定位,涉及到瀏覽器,手機里面的用戶交互展示的內容,都屬于前端。對自己有好處因為多次和阿里的面試官進行了電話面試溝通,所以這些不只是一個面試官提出的問題,而是多個面試官提出的問題。保持一個虛心學習的狀態(tài)。 介紹 狹義的來講,前端指的就是我們常說的html, css, javascript. 三者必不可缺. 而其中涵蓋的知識點不可一篇文章就能完整的講述出來的。廣義的定位,涉及到瀏覽器...
摘要:前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點分為新聞熱點開發(fā)教程工程實踐深度閱讀開源項目巔峰人生等欄目。對該漏洞的綜合評級為高危。目前,相關利用方式已經在互聯(lián)網(wǎng)上公開,近期出現(xiàn)攻擊嘗試爆發(fā)的可能。 前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點;分為新聞熱點、開發(fā)教程、工程實踐、深度閱讀、開源項目、巔峰人生等欄目。歡...
摘要:又將整個文藝類閱讀系統(tǒng)的業(yè)務劃分為兩大部分,分別是面向管理員和合作作者的后臺管理系統(tǒng)和面向用戶的移動端,系統(tǒng)的需求分析將圍繞這兩部分進行展開。 效果展示 showImg(https://user-gold-cdn.xitu.io/2018/8/26/16576a709bd02f5f?w=1409&h=521&f=gif&s=30128195); showImg(https://user...
閱讀 2984·2021-11-25 09:43
閱讀 3604·2021-11-24 11:13
閱讀 3376·2021-10-14 09:42
閱讀 2583·2021-09-23 11:53
閱讀 3625·2021-09-22 15:57
閱讀 3240·2021-09-02 09:54
閱讀 3513·2019-08-30 13:47
閱讀 1652·2019-08-29 16:55