摘要:通過實例的方法,就可以綁定事件和處理函數,第一個參數是事件名稱,第二個就是處理事件的回調函數因為處理是過程是異步的,所以結束之后要調用。
在軟件系統的運維中,總有一些事件,需要在特定的時間來觸發執行,這個時候,我們需要用到定時任務。
agenda是nodejs實現的基于mongodb數據庫的分布式定時任務管理系統。agendash則為agenda提供了一個web管理控制臺。
這篇文章,通過一個demo項目,演示了如何使用agenda來管理定時任務。
為什么需要管理定時任務最早用crontab管理來管理定時任務的時候,需要手動去服務器上設置任務,然后還要在服務器上部署定時執行的程序。整個過程依賴手工操作,用起來感覺特別不踏實。那時候在想,應該有一種更方便的管理定時任務的機制,所以盡量在設計上減少定時任務的使用,只在最必要的時候才會使用。
后來看了很多技術分享,看到知乎的分享他們的運維系統的經驗,實現了一個可以配置,并且有精美的管理后臺的定時任務管理系統,能夠在運維后臺方便的對任務進行操作。
現在已經可以簡單的使用agendash和agenda集成,就方便了實現了任務管理,從而可以更專注的實現業務邏輯
實現原理雖然不需要自己再去發明輪子是非常方便的事情,但是還是應該試著去自己動手做一些嘗試,實際實現起來成本比較高,但是思考一下如何實現,還是有價值的。
agenda通過mongodb實現了任務在定時任務處理集群中的共享和鎖定,從而實現了分布式執行定時任務的功能,實現了更高的可用性;
再結合作為express插件開發的agendash,我們就可以通過管理后臺查詢和管理定時任務。
實現思路如果我自己實現的話,首先要考慮定時任務如何設置,就是語法,agenda并沒有自己發明輪子,而是使用了已有的cron模塊,該模塊的定時任務配置語法,和crontab一樣,是形如*/5 * * * *的形式。
我們要考慮的是定時任務的機制,程序執行之后,一直在進程中輪詢,是否符合觸發條件,如果符合觸發條件,就會觸發設置的要執行的業務邏輯相關代碼,crontab實際上也是觸發執行shell腳本的代碼。最后由業務邏輯代碼根據自己的實際情況運行。
任務的調用,可以用觀察者模式實現。在nodejs中,可以方便的使用回調函數,將任務的名字和回調函數綁定,這樣,任務條件達到的時候,就會觸發執行回調函數;可以結合nodejs的queue隊列模塊來實現。
只有把任務用專有的數據結構存儲起來,才有可能實現某種任務本身的邏輯,需要什么樣的邏輯,就需要什么樣的數據結構做支撐。因此mongodb中要存儲的數據包括:執行條件、任務名稱、創建時間、上次開始時間、上次完成時間、下次執行時間、目前是否在鎖定狀態。
這樣,某個節點執行是,正好符合條件,它先設置任務狀態為鎖定,然后調用回調函數,完成之后,在解除鎖定,并且設置相應的時間;如果出現程序意外崩潰,其他節點檢查是否超過一定處理時間,會將任務的鎖定狀態解除,然后接下來的其他節點,就會檢查并且執行任務。
使用agenda和agendashagenda本身運行,是不需要web服務器;要使用agendash,目前必須安裝express,將agendash作為插件添加到express中,就可以正常的訪問。
演示程序的具體步驟如下:
安裝依賴包
搭建express腳手架
添加agenda任務和任務處理代碼
編寫簡單的測試
添加集成相關配置
安裝依賴包項目需要用到的依賴包分為三類,基本業務邏輯需要,es6編譯相關、還有測試依賴包。以下命令不包含babel相關依賴,請參看其他網上的教程。
npm install --saveagenda agendash express mongoose ejs npm install --save-dev mocha chai supertest搭建express腳手架和agendash
import path from "path" import "./config" import {agendash } from "./middlewares" var express = require("express"); var app = express(); var router = express.Router(); app.set("view engine","ejs"); app.set("views", "./views") app.set("view options",{ "open":"{{", "close":"}}" }); app.use(express.static("public")); ... ... app.use("/agendash", agendash); app.listen(8080, "0.0.0.0")
在express中通過app.use方法,可以加載路由,agendash作為一個插件,直接通過調用use方法,就可以添加到express的路由中,項目中,將agendash的相關路由,添加到/agendash下,這樣的話,訪問地址就是http://localhost:8080/agendash/#
添加agenda任務和任務處理代碼首先實例化一個agenda對象,設置mongodb數據庫連接地址,agenda會處理mongodb連接。
通過agenda實例的define方法,就可以綁定事件和處理函數,第一個參數是事件名稱,第二個就是處理事件的回調函數;因為處理是過程是異步的,所以結束之后要調用done。
agenda在初始化完成之后,會回調綁定的ready方法,在ready中,我們就可以調用agenda的every函數,創建新的定時任務。
將agenda實例作為參數傳給Agendash,后者就會生成能夠操作agenda實例的router。
var Agenda = require("agenda"); var Agendash = require("agendash"); var mongoConnectionString = config["agendaMongodbUrl"] var agenda = new Agenda({db: {address:mongoConnectionString}}) agenda.define("delete old users", function(job, done) { console.log("we will delete user here") done() }); agenda.on("ready", function() { //agenda.every("3 minutes", "delete old users"); agenda.every("*/5 * * * *", "delete old users"); agenda.start(); }); export default Agendash(agenda)編寫簡單的測試
完成編碼之后,我們通過supertest編寫簡單測試,檢查是否可以成功連接mongodb并啟動agendash;要成功運行測試,必須在本地安裝mongodb。
如代碼所示,我們會測試連接agendash的api接口,檢查返回的json數據,是否符合我們創建的定時任務。如果一致,那么測試通過
const app = require("../lib") const request = require("supertest"); var assert = require("assert"); describe("GET /agendash/api", function () { it("should return the correct overview", function (done) { request(app).get("/agendash/api") .expect(200) .expect(function (res) { assert(res.body.title, "Agendash") }) .end(done) }) })添加集成相關配置
因為項目使用了es6語法,所以需要集成babel才能運行程序和測試。我們在package.json中,添加start和test命令的script,在運行和測試的時候,都會用babel來實時編譯es6代碼。為了成功的運行mocha測試,我們還需要設置.babelrc配置文件。
# package.json ... ... "scripts": { "start": "babel-node lib/index.js --presets es2015,stage-2", "test": "./node_modules/.bin/mocha --compilers js:babel-core/register ./test" } # .babelrc { "presets": ["es2015","stage-2"], "plugins": [] } ... ... # 然后我們就可以運行程序 npm install npm start
如果不想自己安裝mongodb或者在本機安裝node_modules,項目的源代碼中提供了docker-compose配置文件,只需要運行docker-compose up命令,就可以運行服務。然后打開瀏覽器查看http://localhost:8080/agendash
示例代碼 https://github.com/liuwill-projects/agenda-cron-demo
文/liuwill(簡書作者)
原文鏈接:用agenda和agendash管理定時任務
著作權歸作者所有,轉載請聯系作者獲得授權,并標注“簡書作者”。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/82213.html
摘要:通過實例的方法,就可以綁定事件和處理函數,第一個參數是事件名稱,第二個就是處理事件的回調函數因為處理是過程是異步的,所以結束之后要調用。 showImg(https://segmentfault.com/img/remote/1460000008845353); 在軟件系統的運維中,總有一些事件,需要在特定的時間來觸發執行,這個時候,我們需要用到定時任務。 agenda是nodejs實...
摘要:每周前端開源推薦第六期從名字就可以很容易的看出該項目的作用,解壓縮。同時支持瀏覽器和。是任務調度的項目。初始化定義人物每三分鐘觸發一次觸發一個交互式學習的方式。強烈建議大家先去體驗一下的介紹是由百度團隊開發的一款開源圖表項目。 每周前端開源推薦第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...
摘要:每周前端開源推薦第六期從名字就可以很容易的看出該項目的作用,解壓縮。同時支持瀏覽器和。是任務調度的項目。初始化定義人物每三分鐘觸發一次觸發一個交互式學習的方式。強烈建議大家先去體驗一下的介紹是由百度團隊開發的一款開源圖表項目。 每周前端開源推薦第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...
摘要:每周前端開源推薦第六期從名字就可以很容易的看出該項目的作用,解壓縮。同時支持瀏覽器和。是任務調度的項目。初始化定義人物每三分鐘觸發一次觸發一個交互式學習的方式。強烈建議大家先去體驗一下的介紹是由百度團隊開發的一款開源圖表項目。 每周前端開源推薦第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...
閱讀 3170·2021-09-10 10:51
閱讀 3351·2021-08-31 09:38
閱讀 1639·2019-08-30 15:54
閱讀 3129·2019-08-29 17:22
閱讀 3214·2019-08-26 13:53
閱讀 1960·2019-08-26 11:59
閱讀 3283·2019-08-26 11:37
閱讀 3308·2019-08-26 10:47