用agenda和agendash管理定时任务

在软件系统的运维中,总有一些事件,须要在特定的时间来触发执行,这个时候,咱们须要用到定时任务。javascript

agenda是nodejs实现的基于mongodb数据库的分布式定时任务管理系统。agendash则为agenda提供了一个web管理控制台。java

这篇文章,经过一个demo项目,演示了如何使用agenda来管理定时任务。node

为何须要管理定时任务

最先用crontab管理来管理定时任务的时候,须要手动去服务器上设置任务,而后还要在服务器上部署定时执行的程序。整个过程依赖手工操做,用起来感受特别不踏实。那时候在想,应该有一种更方便的管理定时任务的机制,因此尽可能在设计上减小定时任务的使用,只在最必要的时候才会使用。git

后来看了不少技术分享,看到知乎的分享他们的运维系统的经验,实现了一个能够配置,而且有精美的管理后台的定时任务管理系统,可以在运维后台方便的对任务进行操做。es6

如今已经能够简单的使用agendash和agenda集成,就方便了实现了任务管理,从而能够更专一的实现业务逻辑github

实现原理

虽然不须要本身再去发明轮子是很是方便的事情,可是仍是应该试着去本身动手作一些尝试,实际实现起来成本比较高,可是思考一下如何实现,仍是有价值的。web

agenda经过mongodb实现了任务在定时任务处理集群中的共享和锁定,从而实现了分布式执行定时任务的功能,实现了更高的可用性;mongodb

再结合做为express插件开发的agendash,咱们就能够经过管理后台查询和管理定时任务。docker

实现思路

若是我本身实现的话,首先要考虑定时任务如何设置,就是语法,agenda并无本身发明轮子,而是使用了已有的cron模块,该模块的定时任务配置语法,和crontab同样,是形如*/5 * * * *的形式。shell

咱们要考虑的是定时任务的机制,程序执行以后,一直在进程中轮询,是否符合触发条件,若是符合触发条件,就会触发设置的要执行的业务逻辑相关代码,crontab实际上也是触发执行shell脚本的代码。最后由业务逻辑代码根据本身的实际状况运行。

任务的调用,能够用观察者模式实现。在nodejs中,能够方便的使用回调函数,将任务的名字和回调函数绑定,这样,任务条件达到的时候,就会触发执行回调函数;能够结合nodejs的queue队列模块来实现。

只有把任务用专有的数据结构存储起来,才有可能实现某种任务自己的逻辑,须要什么样的逻辑,就须要什么样的数据结构作支撑。所以mongodb中要存储的数据包括:执行条件、任务名称、建立时间、上次开始时间、上次完成时间、下次执行时间、目前是否在锁定状态。

这样,某个节点执行是,正好符合条件,它先设置任务状态为锁定,而后调用回调函数,完成以后,在解除锁定,而且设置相应的时间;若是出现程序意外崩溃,其余节点检查是否超过必定处理时间,会将任务的锁定状态解除,而后接下来的其余节点,就会检查而且执行任务。

使用agenda和agendash

agenda自己运行,是不须要web服务器;要使用agendash,目前必须安装express,将agendash做为插件添加到express中,就能够正常的访问。

演示程序的具体步骤以下:

  1. 安装依赖包

  2. 搭建express脚手架

  3. 添加agenda任务和任务处理代码

  4. 编写简单的测试

  5. 添加集成相关配置

安装依赖包

项目须要用到的依赖包分为三类,基本业务逻辑须要,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管理定时任务著做权归做者全部,转载请联系做者得到受权,并标注“简书做者”。

相关文章
相关标签/搜索