资讯专栏INFORMATION COLUMN

用agenda和agendash管理定时任务

ranwu / 2493人阅读

摘要:通过实例的方法,就可以绑定事件和处理函数,第一个参数是事件名称,第二个就是处理事件的回调函数因为处理是过程是异步的,所以结束之后要调用。

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

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

示例代码 https://github.com/liuwill-projects/agenda-cron-demo

文/liuwill(简书作者)
原文链接:用agenda和agendash管理定时任务
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/82213.html

相关文章

  • agendaagendash管理定时任务

    摘要:通过实例的方法,就可以绑定事件和处理函数,第一个参数是事件名称,第二个就是处理事件的回调函数因为处理是过程是异步的,所以结束之后要调用。 showImg(https://segmentfault.com/img/remote/1460000008845353); 在软件系统的运维中,总有一些事件,需要在特定的时间来触发执行,这个时候,我们需要用到定时任务。 agenda是nodejs实...

    AZmake 评论0 收藏0
  • 阈值报警功能

    摘要:定义触发规则我们的前端监控,会主要追踪三种报警情况错误率达到设定阈值报警错误率达到阈值报警访问速度慢报警。邮件通知服务目前邮件通知服务也有很多,我们选的是阿里云的邮件推送。配置任务调度,创建实例配置阿里云邮件推送,这里使用方式去发送邮件。 所谓web,即使你我素未谋面,便知志趣相投;足不出户,亦知世界之大。 ​01 - 什么是阈值报警功能 在我们前端监控系统中,虽然我们收集了用户实时访...

    高璐 评论0 收藏0
  • 每周前端开源推荐第六期

    摘要:每周前端开源推荐第六期从名字就可以很容易的看出该项目的作用,解压缩。同时支持浏览器和。是任务调度的项目。初始化定义人物每三分钟触发一次触发一个交互式学习的方式。强烈建议大家先去体验一下的介绍是由百度团队开发的一款开源图表项目。 每周前端开源推荐第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...

    Salamander 评论0 收藏0
  • 每周前端开源推荐第六期

    摘要:每周前端开源推荐第六期从名字就可以很容易的看出该项目的作用,解压缩。同时支持浏览器和。是任务调度的项目。初始化定义人物每三分钟触发一次触发一个交互式学习的方式。强烈建议大家先去体验一下的介绍是由百度团队开发的一款开源图表项目。 每周前端开源推荐第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...

    channg 评论0 收藏0
  • 每周前端开源推荐第六期

    摘要:每周前端开源推荐第六期从名字就可以很容易的看出该项目的作用,解压缩。同时支持浏览器和。是任务调度的项目。初始化定义人物每三分钟触发一次触发一个交互式学习的方式。强烈建议大家先去体验一下的介绍是由百度团队开发的一款开源图表项目。 每周前端开源推荐第六期 43081j / rar.js Pure-JavaScript RAR reader using AJAX, File API...

    worldligang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<