基于agenda的Nodejs定时任务管理框架搭建
0、背景
在大型项目中,定时任务的应用场景越来越广。一般来说,按照微服务的思想,我们会将定时任务单独部署一套服务,核心的业务接口独立到另一个服务中,从而降低相互之间的耦合程度。在需要使用定时任务时,只需要由定时任务微服务定时向核心业务服务发起异步接口调用。
基于NodeJS来搭建这样一套定时任务的话,我们可以使用现有比较成熟的第三方框架来快速搭建,开发人员只需要关注定时任务的实现逻辑即可。
1、agenda
在github搜索nodejs schedule的话会有很多类库,比如node-schedule,agenda,node-cron等。之所以选择agenda的话主要由两个原因:1、agenda接口简单,还可使用人类可读的cron表达式;2、agenda提供了完整的Restful API接口,以及可统计查看操作的UI界面。
这样的话,我们只要在代码中提前定义好定时任务处理逻辑,然后就可以在界面在新增或者移除定时任务安排,而无需重新上线。
下面我们就开始从头搭建基于agenda的定时任务。
2、基础环境准备
- MongoDB:agenda需要使用MongoDB来存储定时任务数据。建议大家使用docker进行一建安装,操作简单,删除也方便。只需要docker中搜索mongo,选择安装默认推荐的官方版即可。
- agenda:定时任务管理框架,文档参考:https://github.com/agenda/agenda
- agendash:基于agenda的UI管理界面,文档参考:https://github.com/agenda/agendash
- express:用于配合agendash启动WEB服务
- nirvana-logger:非必选,nodejs日志输出框架,文档参考:https://www.npmjs.com/package/nirvana-logger
3、样例代码
// 框架引入
var express = require('express');
var app = express(); var Agenda = require('agenda');
var Agendash = require('agendash');
var L = require('nirvana-logger')('agenda') // agenda初始化,并连接MongoDB
var agenda = new Agenda({db: {address: 'mongodb://localhost:32768/agenda'}}); // 定义一个测试任务
agenda.define('testJob', function (job, done) {
try {
L('hello',job.attrs.data, new Date())
done()
}catch (err) {
done(new Error(err))
}
}) // agenda框架启动
agenda.on('ready', function () {
L("====>>>agenda启动成功<<<<===")
agenda.start();
}) // Agendash UI界面
app.listen(3000);
app.use('/dash', Agendash(agenda));
13行:定义一个任务,名称为testJob,后续我们可以通过该名字安排定时任务。第二个参数是一个函数,用于处理我们的业务逻辑,需要注意的是,我们需要在任务完成之后主动调用done方法,这样agenda才会将任务标记为完成。
17行:如果任务执行过程中出现异常(比如网络请求异常)时,需要向done传入一个error对象,agenda会将此任务标记为fail状态。
23行:在agenda连接MongoDB成功后,会触发ready的钩子,我们才能在这里开始安排定时任务,并且让agenda开始执行定时任务扫描。
29行:在3000端口启动express,同时使用agendash框架启动agenda的WEB管理界面。
执行node命令启动该js文件,如果能在命令行看到“agenda启动成功”则表示agenda连接数据库成功并且成功启动。
其实细心的同学可以,我们在上面的代码中只是定义了任务,但是并没有对进行对任务进行定时运行。
所以接下来我们将演示如何在WEB界面上对定时任务进进行查询,新增以及删除的操作。
现在我们可以打开:http://localhost:3000/dash/# 来查看web界面。
4、定时任务界面管理
打开agendash的默认界面是这样

从界面上也可以看出,我们现在的确并未启动任何定时任务。
4.1 新增定时任务
点击【Schedule job】,在后面弹出create job界面:

Job name:我们需要使用的任务名称,即我们在程序中提前设置好的任务,比如刚才定义的testJob
Schedule:安排定时任务,这里我们输入希望定时任务执行的时间点,比如5 minutes。这里时间的支持具体请参考:https://github.com/agenda/human-interval
Repeat every:循环执行定时任务,这里输入循环间隔时间。比如5 seconds。这里需要注意的是schedule安排的任务只会执行一次,repeat任务会一直循环执行。所以这二者一般只需要按需求填一个即可。
Job data:向定时任务传入的额外数据,我们可以在任务执行时通过job.attr.data获取到这些参数。
点击保存后,我们的定时任务就开始运行,可以看到控制台开始循环执行打印日志:

同时WEB界面数据将会更新,我们也能看到定时任务的运行状态:

schedule安排一次性的定时任务也是类似的操作,大家可以自己尝试。
值得注意的是,我们定义的任务,是可以被重复执行定时任务。
4.2 移除定时任务
点击某一个定时任务,就能查看到任务的详细信息以及相关操作。
点击右上角的【delete selected】即可删除该定时任务。

5、几个注意点
- 定时任务的时间除了使用cron表达式以外,还只能简单的英文表达,具体要参考https://github.com/agenda/human-interval
- 定时任务在执行过程中会将设置为锁定状态,任务执行完成以后再将任务锁定状态解除。所以如果任务在执行过程中,程序退出的话,那么就会导致任务一直处于锁定状态,agenda默认10分钟后自动解锁任务。
- 为避免定时任务重复执行,一般来讲定时任务微服务我们只需要部署一个实例即可。核心的业务接口处于负载均衡的考虑,可以按业务量多部署几个实例。
基于agenda的Nodejs定时任务管理框架搭建的更多相关文章
- (一)熟悉执行流程——基于ThinkPHP3.2的内容管理框架OneThink学习
ThinkPHP作为国内具有代表性的PHP框架,经过多年的发展,受到越来越多公司与开发者的青睐.我也在忙里偷闲中抽出部分时间,来学习这个优秀的框架.在开始学习这个框架时,最好通过实例来学习,更容易结合 ...
- NodeJs之服务搭建与数据库连接
NodeJs之服务搭建与数据库连接 一,介绍与需求分析 1.1,介绍 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境. Node.js 使用了一个事件驱动.非阻 ...
- 基于腾讯Centos7云服务器搭建SVN版本控制库
基于腾讯Centos7云服务器搭建SVN版本控制库 最近在和小伙伴组队参加一个关于人工智能的比赛,无奈不知道怎么处理好每个人的代码托管问题,于是找到了晚上免费svn托管服务器的服务,但是所给的免费空间 ...
- 基于zookeeper的Swarm集群搭建
简介 Swarm:docker原生的集群管理工具,将一组docker主机作为一个虚拟的docker主机来管理. 对客户端而言,Swarm集群就像是另一台普通的docker主机. Swarm集群中的每台 ...
- 基于Docker的TensorFlow机器学习框架搭建和实例源码解读
概述:基于Docker的TensorFlow机器学习框架搭建和实例源码解读,TensorFlow作为最火热的机器学习框架之一,Docker是的容器,可以很好的结合起来,为机器学习或者科研人员提供便捷的 ...
- 基于centos6.5 hbase 集群搭建
注意本章内容是在上一篇文章“基于centos6.5 hadoop 集群搭建”基础上创建的 1.上传hbase安装包 hbase-0.96.2-hadoop2 我的目录存放在/usr/hadoop/hb ...
- 基于Docker部署nodejs应用
基于Docker部署nodejs应用 背景 公司基于Vue.js的项目最近需要部署到云端,因此需要先行在公司内部Docker环境下验证相关技术,因而有本文之前提. 本文展示在Docker容器中,应用部 ...
- 使用基于 PHP 的开源软件 YOURLS 搭建短链接地址服务
使用基于 PHP 的开源软件 YOURLS搭建 系统配置 php7.1+mysql5.7+nginx 下载源代码 git clone https://github.com/YOURLS/YOURLS. ...
- NodeJS开发环境搭建
原创作者: zero20121222 NodeJS开发环境搭建 1.安装NodeJS 1.编译环境 源代码编译器,通常 Unix/Linux平台都自带了C++的编译器(GCC/G++).如果没有,请通 ...
随机推荐
- js解析jsonArray嵌套
{ "data": { "BTC": [ 14781.51, 14888.9, 14900.04, 15098.88, 15308, 14880.01, 149 ...
- Java通配符解惑
T 有类型 ? 未知类型 一.通配符的上界 既然知道List<Cat>并不是List<Anilmal>的子类型,那就需要去寻找替他解决的办法, 是AnimalTrianer ...
- MySQL改写子查询成Join
有时用别的方式而不是子查询可以获得更高的性能 : For example: SELECT * FROM t1 WHERE id IN (SELECT id FROM t2); 改写: SELECT D ...
- main函数的两个参数
#include "stdio.h" int main(int argc ,char **argv) { printf("argc = %d \n",argc) ...
- 修真院java后端工程师学习课程--任务1(day four)
今天学习的是spring框架,内容主要有: spring的概念,主要是做什么的: Spring是一个基于IOC和AOP的结构J2EE系统的框架 IOC 反转控制 是Spring的基础,Inversio ...
- js 原型 对象篇
一切皆对象 js中 值类型就不是对象 剩下的都是对象(也就是引用类型) typeof()运算符 判断四种值类型 typeof 10; --> Number || typeof &quo ...
- Django 类方式view进行进行用户验证
问题: Django中,view的书写方式有两种,一种是def函数方式,一种是class方式,函数方式通过@login_required装饰器标记函数,就必须通过用户验证,而类,则没办法通过此方法进行 ...
- java.lang.IllegalArgumentException: Document base D:\Project\workspace\space\.metadata\.plugins\org.eclipse.wst.server.core\tmp7\wtpwebapps\Blog
java.lang.IllegalArgumentException: Document base D:\Project\workspace\space\.metadata\.plugins\org. ...
- j2e中操作EXCEL
在j2e中操作excel,无非2种情况,在这里我贴部分代码做个例子就OK,不管是导入和导出都是操作的都是流 1,导入,浏览器输入EXCEL到java后台解析 package action; impor ...
- UUID.randomUUID().toString()
UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法.UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机 ...