在软件体系的运维中,总有一些事宜,须要在特定的时刻来触发实行,这个时刻,我们须要用到定时使命。
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和agendash
agenda自身运转,是不须要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
文/liuwill(简书作者)
原文链接:用agenda和agendash治理定时使命
著作权归作者一切,转载请联络作者取得受权,并标注“简书作者”。