摘要:通過實例的方法,就可以綁定事件和處理函數(shù),第一個參數(shù)是事件名稱,第二個就是處理事件的回調(diào)函數(shù)因為處理是過程是異步的,所以結(jié)束之后要調(diào)用。
在軟件系統(tǒng)的運維中,總有一些事件,需要在特定的時間來觸發(fā)執(zhí)行,這個時候,我們需要用到定時任務(wù)。
agenda是nodejs實現(xiàn)的基于mongodb數(shù)據(jù)庫的分布式定時任務(wù)管理系統(tǒng)。agendash則為agenda提供了一個web管理控制臺。
這篇文章,通過一個demo項目,演示了如何使用agenda來管理定時任務(wù)。
為什么需要管理定時任務(wù)最早用crontab管理來管理定時任務(wù)的時候,需要手動去服務(wù)器上設(shè)置任務(wù),然后還要在服務(wù)器上部署定時執(zhí)行的程序。整個過程依賴手工操作,用起來感覺特別不踏實。那時候在想,應該有一種更方便的管理定時任務(wù)的機制,所以盡量在設(shè)計上減少定時任務(wù)的使用,只在最必要的時候才會使用。
后來看了很多技術(shù)分享,看到知乎的分享他們的運維系統(tǒng)的經(jīng)驗,實現(xiàn)了一個可以配置,并且有精美的管理后臺的定時任務(wù)管理系統(tǒng),能夠在運維后臺方便的對任務(wù)進行操作。
現(xiàn)在已經(jīng)可以簡單的使用agendash和agenda集成,就方便了實現(xiàn)了任務(wù)管理,從而可以更專注的實現(xiàn)業(yè)務(wù)邏輯
實現(xiàn)原理雖然不需要自己再去發(fā)明輪子是非常方便的事情,但是還是應該試著去自己動手做一些嘗試,實際實現(xiàn)起來成本比較高,但是思考一下如何實現(xiàn),還是有價值的。
agenda通過mongodb實現(xiàn)了任務(wù)在定時任務(wù)處理集群中的共享和鎖定,從而實現(xiàn)了分布式執(zhí)行定時任務(wù)的功能,實現(xiàn)了更高的可用性;
再結(jié)合作為express插件開發(fā)的agendash,我們就可以通過管理后臺查詢和管理定時任務(wù)。
實現(xiàn)思路如果我自己實現(xiàn)的話,首先要考慮定時任務(wù)如何設(shè)置,就是語法,agenda并沒有自己發(fā)明輪子,而是使用了已有的cron模塊,該模塊的定時任務(wù)配置語法,和crontab一樣,是形如*/5 * * * *的形式。
我們要考慮的是定時任務(wù)的機制,程序執(zhí)行之后,一直在進程中輪詢,是否符合觸發(fā)條件,如果符合觸發(fā)條件,就會觸發(fā)設(shè)置的要執(zhí)行的業(yè)務(wù)邏輯相關(guān)代碼,crontab實際上也是觸發(fā)執(zhí)行shell腳本的代碼。最后由業(yè)務(wù)邏輯代碼根據(jù)自己的實際情況運行。
任務(wù)的調(diào)用,可以用觀察者模式實現(xiàn)。在nodejs中,可以方便的使用回調(diào)函數(shù),將任務(wù)的名字和回調(diào)函數(shù)綁定,這樣,任務(wù)條件達到的時候,就會觸發(fā)執(zhí)行回調(diào)函數(shù);可以結(jié)合nodejs的queue隊列模塊來實現(xiàn)。
只有把任務(wù)用專有的數(shù)據(jù)結(jié)構(gòu)存儲起來,才有可能實現(xiàn)某種任務(wù)本身的邏輯,需要什么樣的邏輯,就需要什么樣的數(shù)據(jù)結(jié)構(gòu)做支撐。因此mongodb中要存儲的數(shù)據(jù)包括:執(zhí)行條件、任務(wù)名稱、創(chuàng)建時間、上次開始時間、上次完成時間、下次執(zhí)行時間、目前是否在鎖定狀態(tài)。
這樣,某個節(jié)點執(zhí)行是,正好符合條件,它先設(shè)置任務(wù)狀態(tài)為鎖定,然后調(diào)用回調(diào)函數(shù),完成之后,在解除鎖定,并且設(shè)置相應的時間;如果出現(xiàn)程序意外崩潰,其他節(jié)點檢查是否超過一定處理時間,會將任務(wù)的鎖定狀態(tài)解除,然后接下來的其他節(jié)點,就會檢查并且執(zhí)行任務(wù)。
使用agenda和agendashagenda本身運行,是不需要web服務(wù)器;要使用agendash,目前必須安裝express,將agendash作為插件添加到express中,就可以正常的訪問。
演示程序的具體步驟如下:
安裝依賴包
搭建express腳手架
添加agenda任務(wù)和任務(wù)處理代碼
編寫簡單的測試
添加集成相關(guān)配置
安裝依賴包項目需要用到的依賴包分為三類,基本業(yè)務(wù)邏輯需要,es6編譯相關(guān)、還有測試依賴包。以下命令不包含babel相關(guān)依賴,請參看其他網(wǎng)上的教程。
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作為一個插件,直接通過調(diào)用use方法,就可以添加到express的路由中,項目中,將agendash的相關(guān)路由,添加到/agendash下,這樣的話,訪問地址就是http://localhost:8080/agendash/#
添加agenda任務(wù)和任務(wù)處理代碼首先實例化一個agenda對象,設(shè)置mongodb數(shù)據(jù)庫連接地址,agenda會處理mongodb連接。
通過agenda實例的define方法,就可以綁定事件和處理函數(shù),第一個參數(shù)是事件名稱,第二個就是處理事件的回調(diào)函數(shù);因為處理是過程是異步的,所以結(jié)束之后要調(diào)用done。
agenda在初始化完成之后,會回調(diào)綁定的ready方法,在ready中,我們就可以調(diào)用agenda的every函數(shù),創(chuàng)建新的定時任務(wù)。
將agenda實例作為參數(shù)傳給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數(shù)據(jù),是否符合我們創(chuàng)建的定時任務(wù)。如果一致,那么測試通過
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) }) })添加集成相關(guān)配置
因為項目使用了es6語法,所以需要集成babel才能運行程序和測試。我們在package.json中,添加start和test命令的script,在運行和測試的時候,都會用babel來實時編譯es6代碼。為了成功的運行mocha測試,我們還需要設(shè)置.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命令,就可以運行服務(wù)。然后打開瀏覽器查看http://localhost:8080/agendash
示例代碼 https://github.com/liuwill-projects/agenda-cron-demo
文/liuwill(簡書作者)
原文鏈接:用agenda和agendash管理定時任務(wù)
著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),并標注“簡書作者”。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/82213.html
摘要:通過實例的方法,就可以綁定事件和處理函數(shù),第一個參數(shù)是事件名稱,第二個就是處理事件的回調(diào)函數(shù)因為處理是過程是異步的,所以結(jié)束之后要調(diào)用。 showImg(https://segmentfault.com/img/remote/1460000008845353); 在軟件系統(tǒng)的運維中,總有一些事件,需要在特定的時間來觸發(fā)執(zhí)行,這個時候,我們需要用到定時任務(wù)。 agenda是nodejs實...
摘要:每周前端開源推薦第六期從名字就可以很容易的看出該項目的作用,解壓縮。同時支持瀏覽器和。是任務(wù)調(diào)度的項目。初始化定義人物每三分鐘觸發(fā)一次觸發(fā)一個交互式學習的方式。強烈建議大家先去體驗一下的介紹是由百度團隊開發(fā)的一款開源圖表項目。 每周前端開源推薦第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...
摘要:每周前端開源推薦第六期從名字就可以很容易的看出該項目的作用,解壓縮。同時支持瀏覽器和。是任務(wù)調(diào)度的項目。初始化定義人物每三分鐘觸發(fā)一次觸發(fā)一個交互式學習的方式。強烈建議大家先去體驗一下的介紹是由百度團隊開發(fā)的一款開源圖表項目。 每周前端開源推薦第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...
摘要:每周前端開源推薦第六期從名字就可以很容易的看出該項目的作用,解壓縮。同時支持瀏覽器和。是任務(wù)調(diào)度的項目。初始化定義人物每三分鐘觸發(fā)一次觸發(fā)一個交互式學習的方式。強烈建議大家先去體驗一下的介紹是由百度團隊開發(fā)的一款開源圖表項目。 每周前端開源推薦第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...
閱讀 3186·2021-09-10 10:51
閱讀 3369·2021-08-31 09:38
閱讀 1660·2019-08-30 15:54
閱讀 3147·2019-08-29 17:22
閱讀 3225·2019-08-26 13:53
閱讀 1978·2019-08-26 11:59
閱讀 3294·2019-08-26 11:37
閱讀 3324·2019-08-26 10:47