node的轻量级消息队列

477 阅读2分钟

最早接触kue是在0.7之前的版本,功能很少,很弱,但还是很好用的,那时候找过一些其他的消息队列,如rabbitmq,kafka之类的,但是都觉得太重了,跟nodejs的融合还是不太合适。

找着找着,就找到了tj大神搞的kue,基于redis的subpub做的优先级消息队列,适合做一些离线任务,比如统计运算、发邮件消息以及异步业务逻辑。

建议初次使用多看看文档,把一些方法全部记下来作为模板,比如创建第一个任务的时候:

queue.create(YOUR_FIRST_JOB, jobData)
.removeOnComplete(true)
.priority('normal')
.attempts(5)
.backoff( {delay: 60*1000, type:'exponential'} )
.ttl(ms('1h'))
.save();

文档

文档很弱,继承了一贯懒的作风,很多不明白的地方还是看代码来的快,如果你发现文档中没有的内容,或者写错的内容,尽快提交pr。

延时任务

不能自动执行延时任务,必须执行一个周期性检查(记得是500ms,也可以自定义)的方法,然后还不能在多个进程中执行,不然会有race condition出现,即同一时刻同时执行同一个任务。
新的版本中kue自动处理,已经没有这个问题了。

任务堵塞

还有一旦redis的连接不稳定,或者没有处理好throw error,就会出现任务永远处于active状态,因为kue认为这个任务没有完成。如果这时候设置的
新的版本中,提供了ttl超时自动失败,以及watchStuckJobs这个方法,建议在创建job之前就调用这个方法。

queue.watchStuckJobs(interval=1000)

运维

除了kue自带的dashboard,还有kue-ui,感觉比自带的好用一些。还有就是经常查看是否有失败的任务,用kue自带的一些方法定期去执行,然后把结果用邮件发送之类的。

部署&重启

如果是用的pm2,记得不要直接restart或者reload,而是要用gracefulReload,pm2会给进程发送一个shutdown的message,等它自动退出,如果超出时间未响应才会kill,因为对于kue来说,可能正在跑某个人物,如果这时候直接restart会影响到任务。

// remember to set env PM2_GRACEFUL_LISTEN_TIMEOUT
// and process.send('online') when job app start
process.once( 'message', function ( msg ) {
  if (msg !== 'shutdown') return;
  queue.shutdown( 5000, function(err) {
    console.log( 'Kue shutdown: ', err||'' );
    process.exit( 0 );
  });
});