使用NODEJS+REDIS开发一个消息队列以及定时任务处理
作者:RobanLee
原创文章,转载请注明: 萝卜李 http://www.robanlee.com
源码在这里: https://github.com/robanlee123/RobCron
时间有限,就不详细注释,有问题或者意见欢迎@我,也欢迎大家批评指正.
本文所必须的一些资料如下:
1. NODEJS ==> 可以去NODEJS.ORG下载最新的源码.
2. Redis ==> Redis.io
3. KUE ==> Nodejs的一个开源队列系统
4. NODE-SCHEDULE ==> NODEJS 一个开源调度系统
废话不多说,先来介绍任务的流程:
1. NODEJS或者PHP或者其他语言 写入REDIS 一个计划任务, 比如每分钟做某件事,这里就用SAYHELLO来代替好了
2. 使用NODEJS读取这个任务,并将它转换为NODE的调度任务(node-schedule 来完成)
3. 调度器[node-schedule]根据设定的规则来分发任务.
4. KUE接受任务,并且加入列队,执行.
5. DONE
STEP1: 创建一个任务
/**
* Add task
* @author Robanlee@gmail.com
*/ //加载函数,集中加载一些LIB,这个源码请参照最后的附属文件
var loader = require('./loader'); function addTask(opts){
new loader(this);
//默认设置
this.opts = {
keyIDs:'schedule:job:ids',
keyLists:'schedule:job:list',
keyJob:'schedule:job:'
}
//合并配置,类似JQUERY: extend
this.mergeParams(opts);
}; //Merge options
addTask.prototype.mergeParams = function ( param ){
if(undefined === this.opts ) {
return false;
}
for(var x in param) {
if(param[x] != undefined && '' != param[x]) {
this.opts[x] = param[x];
}
}
}; //添加数据方法
addTask.prototype.pushData = function ( data ){
if(undefined == data ) {
console.log('--ERROR:data is null');
return false;
}
this.getIncr.call(this,function(response,obj){
var id = response;
obj.redisClient.rpush(obj.opts.keyLists,id,function(err,response){
if(err) throw err;
});
data.id = id;
var m = obj.redisClient.multi();
for(var x in data) {
m.hset( obj.opts.keyJob+id,x,data[x] );
}
m.exec(function(err,response){
if(err) throw err;
console.log('[info] Task: ['+data.name+'] has been set successful!');
});
});
}; //获取REDIS目前的自增ID
addTask.prototype.getIncr = function (callBack){
var obj = this;
this.redisClient.incr(this.opts.keyIDs,function(err,response){
console.log("[info] Current id is : " + response);
callBack(response, obj);
});
};
加载这个lib 写入一个DEMO:
var data = {
'name':'taskDemo',
'created':Date.now(),
'state':1,
'type':'untitled',
'rule':'*/1 * * * *' //这个任务规则可以为CRONTAB的规则,这个表示每分钟执行一次
};
var job = new addTask();
job.pushData(data);
执行这个脚本,如果一切正常,你会看到如下信息:
NODEJS 输出:

REDIS:

接下来就是获取数据,并且转换为调度任务了,
源码:
var loader = require('./loader');
var taskLog = require("./TaskLog");
function scheduleTask(){
new loader(this);
this.opts = {
keyIDs:'schedule:job:ids',
keyLists:'schedule:job:list',
keyJob:'schedule:job:'
}
this.task = {
taskDemo:undefined
};
//监听取消任务操作
this.listenCancel();
};
scheduleTask.prototype.setScheduleTask = function (data,obj){
this.task[data.name] = this.libs['node-schedule'].scheduleJob(data.rule,function(){
obj.setQueue(data);
console.log('[info] Task :' + data.name + ' has been set in queue!');
});
};
scheduleTask.prototype.setQueue = function (datas){
var jobs = this.libs.kue.createQueue();
jobs.create(datas.name,{
'name:':datas.name,
'state':1
}).save();
console.log("[info] Task ["+datas.name+"] has been queued!");
this.setLog(datas);
};
scheduleTask.prototype.setLog = function (responseData){
var logData = {
jobid:responseData.id,
name:responseData.name,
result:1
};
new taskLog(logData);
console.log("[info] Task has been loged");
};
scheduleTask.prototype.getJob = function (){
this.getJobIndex.call(this,function(response,obj){
for(var x in response ) {
obj.redisClient.hgetall(obj.opts.keyJob+response[x],function(err,data){
console.log("[info] Task:["+data.name+"] has been loaded!");
obj.setScheduleTask(data, obj);
});
}
});
};
scheduleTask.prototype.getJobIndex = function(callBack){
//Read tasks from <list schedule:job:list>
var o = this;
this.redisClient.lrange(this.opts.keyLists,0,-1,function(err,response){
if(err) throw err;
callBack(response, o);
});
};
scheduleTask.prototype.listenCancel = function (){
var job = this.libs.kue.createQueue();
var that = this;
job.process('cancelJob',function(data,done){
that.task[data.data.data].cancel();
console.log('[info] Task: '+data.data.data + ' has been canceled') ;
done();
});
}
执行代码:
var x = new scheduleTask();
x.getJob();
等待一分钟后,NODEJS控制台会输出(这个任务在没有取消的情况下,每分钟都会执行):

第二分钟:

REDIS 现在的数据:

这个数据中增加了KUE的一些任务, q:job:[]:inactive 这个就标识任务还未被执行,执行后的任务状态有
complete active failed delay 四种
至此,就只剩下执行任务的步骤了
var loader = require('./loader');
function execTask(){
new loader(this);
var job = this.libs.kue.createQueue();
job.process('taskDemo',function(data,done){
console.log('[info] Task:'+data.type+'#'+data.id+' has been executed successful!');
//DONE之前可以做你想要做的事情
done(); //千万别忘记调用此方法
});
}
//添加一个取消定时任务的KUE任务
execTask.prototype.addCancelJob = function (){
var job =this.libs.kue.createQueue();
job.create('cancelJob', {data:'taskDemo'}).save();
console.log('[info] Task: cancelJob has been send!');
}
执行这个脚本:
var et = new execTask(); //取消定时任务
et.addCancelJob();
执行后会有2个结果
1. 程序会执行当前列队里的任务.
2. 定时任务会被取消,下一分钟后任务不会再由SCHEDULE分配
任务执行结果:

取消任务的回应:

注意最后一行…
使用NODEJS+REDIS开发一个消息队列以及定时任务处理的更多相关文章
- 如何使用NODEJS+REDIS开发一个消息队列
作者: RobanLee 原创文章,转载请注明: 萝卜李 http://www.robanlee.com MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应 ...
- 什么鬼,面试官竟然让我用Redis实现一个消息队列!!?
GitHub 9.4k Star 的Java工程师成神之路 ,不来了解一下吗? GitHub 9.4k Star 的Java工程师成神之路 ,真的不来了解一下吗? GitHub 9.4k Star 的 ...
- Redis 学习笔记(六)Redis 如何实现消息队列
一.消息队列 消息队列(Messeage Queue,MQ)是在分布式系统架构中常用的一种中间件技术,从字面表述看,是一个存储消息的队列,所以它一般用于给 MQ 中间的两个组件提供通信服务. 1.1 ...
- Redis+php-resque实现消息队列
服务器硬件配置 Dell PowerEdge R310英特尔单路机架式服务器 Intel Xeon Processor X3430 2.4GHz, 8MB Cache 8GB内存(2 x 4GB) ...
- Redis实现简单消息队列
http://www.jianshu.com/p/9c04890615ba 任务异步化 打开浏览器,输入地址,按下回车,打开了页面.于是一个HTTP请求(request)就由客户端发送到服务器,服务器 ...
- Delayer 基于 Redis 的延迟消息队列中间件
Delayer 基于 Redis 的延迟消息队列中间件,采用 Golang 开发,支持 PHP.Golang 等多种语言客户端. 参考 有赞延迟队列设计 中的部分设计,优化后实现. 项目链接:http ...
- Spring Cloud(7):事件驱动(Stream)分布式缓存(Redis)及消息队列(Kafka)
分布式缓存(Redis)及消息队列(Kafka) 设想一种情况,服务A频繁的调用服务B的数据,但是服务B的数据更新的并不频繁. 实际上,这种情况并不少见,大多数情况,用户的操作更多的是查询.如果我们缓 ...
- 进阶高阶IoT架构-教你如何简单实现一个消息队列
前言 消息队列是软件系统领域用来实现系统间通信最广泛的中间件.基于消息队列的方式是指由应用中的某个系统负责发送消息,由关心这条消息的相关系统负责接收消息,并在收到消息后进行各自系统内的业务处理.消息可 ...
- skynet源代码学习 - 从全局队列中弹出/压入一个消息队列过程
学习云风的skynet源代码,简单记录下. void skynet_globalmq_push(struct message_queue * queue) { struct global_queue ...
随机推荐
- OpenCV——Haar-like特征
Haar-like特征--即Haar特征,是计算机视觉领域一种常用的特征描述算子.它最早用于人脸描述. 目前常用的Haar-like特征可以分为以下几类:线性特征.边缘特征.点特征(中心特征).对角线 ...
- Windows,Linux换行知识
换行符在写文件的时候用得上 Linux: "\n"Windows: "\r\n" 注意:换行符一定要加上双引号,单引号是没有用的.
- Hibernate之通过hibernate.cfg.xml配置文件访问数据库的例子
hibernate.cfg.xml文件内容: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ...
- PHP基础示例:用PHP+Mysql编写简易新闻管理系统
实现目标:使用php和mysql操作函数实现一个新闻信息的发布.浏览.修改和删除操作 实现步骤: 一.创建数据库和表 1.创建数据库和表:newsdb 2.创建表格:news 字段:新闻id,标题,关 ...
- C语言运算符的注意问题
//对于自增和自减运算符的运算规律值得研究,小心被坑.1 #include<stdio.h> int main(void){ ,j=,p,q; p=(i++)+(i++)+(i++); q ...
- 常用两种数据交换格式之XML和JSON的比较
目前,在web开发领域,主要的数据交换格式有XML和JSON,对于XML相信每一个web developer都不会感到陌生: 相比之下,JSON可能对于一些新步入开发领域的新手会感到有些陌生,也可能你 ...
- js加载优化-二
http://www.cnblogs.com/radom/archive/2011/04/26/2028886.html ontrolJS 主要为了是解决网页加载中Js文件的性能问题,ControlJ ...
- WPF笔记(1.8 资源与映射)——Hello,WPF!
原文:WPF笔记(1.8 资源与映射)--Hello,WPF! 终于,看明白了,已经是凌晨1:39分.这本书这一节写得实在是不好,一个local搞得我糊里糊涂,于是,准备按照他的思路,按照我的理解,改 ...
- 【Android病毒分析报告】 - ZooTiger “集恶意推广、隐私窃取、恶意吸费于一体”
本文章由Jack_Jia编写,转载请注明出处. 文章链接:http://blog.csdn.net/jiazhijun/article/details/11772379 作者:Jack_Jia ...
- FNN模糊神经网络——信息系统客户服务感知评价
案例描述 信息系统是否真正减轻业务人员的日常工作量提高工作效率?如何从提供“被动”服务转变为根据客户感知提供“主动”服务,真正实现电网企业对信息系统服务的有效管理?如何构建一套适合企业的信息系统客户服 ...