基于agenda的Nodejs定时任务管理框架搭建

时间:2024-01-23 12:14:55

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、样例代码

 1 // 框架引入
 2 var express = require(\'express\');
 3 var app = express();
 4 
 5 var Agenda = require(\'agenda\');
 6 var Agendash = require(\'agendash\');
 7 var L = require(\'nirvana-logger\')(\'agenda\')
 8 
 9 // agenda初始化,并连接MongoDB
10 var agenda = new Agenda({db: {address: \'mongodb://localhost:32768/agenda\'}});
11 
12 // 定义一个测试任务
13 agenda.define(\'testJob\', function (job, done) {
14   try {
15     L(\'hello\',job.attrs.data, new Date())
16     done()
17   }catch (err) {
18     done(new Error(err))
19   }
20 })
21 
22 // agenda框架启动
23 agenda.on(\'ready\', function () {
24   L("====>>>agenda启动成功<<<<===")
25   agenda.start();
26 })
27 
28 // Agendash UI界面
29 app.listen(3000);
30 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分钟后自动解锁任务。
  • 为避免定时任务重复执行,一般来讲定时任务微服务我们只需要部署一个实例即可。核心的业务接口处于负载均衡的考虑,可以按业务量多部署几个实例。