RabbitMQ官方提供的教程https://www.rabbitmq.com/tuto...,是基于回调的。

下面将给出基于Promise式的写法。并且实现动态的队列绑定

初始化配置


const amqp = require('amqplib')
// rabbitMQ地址
const {amqpAddrHost} = require('../config/index.js') // 交换机名称
const ex = 'amq.topic' const amqpAddr = `amqp://${amqpAddrHost}` // 读取HOSTNAME, 在跑多实例时,例如在k8s中,HOSTNAME可以获取当前pod的名称
// 多实例时,写日志,或者建立连接时,最好带上pod名称,如果出现问题,也比较好定位哪个pod出现的问题。
const hostName = process.env.HOSTNAME // 队列的属性设置
// 一般来说,最好设置队列自动删除autoDelete,当链接断开时,队列也会删除,这样不会产生非常多的无用队列
// durable是用来的持久化的,最好也可以设置成不持久化 const queueAttr = {autoDelete: true, durable: false} // 定义channel的引用,当链接建立时,所有方法都可以通过引用CH来获取channel方法
let CH = null

向队列发送消息的函数


// 向队列发送消息的函数
function publishMessage (msg) {
if (!CH) {
return ''
} msg = JSON.stringify(msg)
// 指定交换机ex, routing key, 以及消息的内容
CH.publish(ex, eventBusTopic, Buffer.from(msg))
}

当链接rabbitMQ断开时,要主动去重连


function reconnectRabbitMq () {
log.info('reconnect_rabbit_mq')
connectRabbitMq()
}

连接rabbitMQ的主要函数


function connectRabbitMq () {
amqp.connect(amqpAddr, {
// 设置connection_name的属性,可以在rabbitMQ的控制台的UI上,看到连接是来自哪个实例
clientProperties: {
connection_name: hostName
}
})
.then((conn) => {
log.info('rabbitmq_connect_successd')
// 一定要加上链接的报错事件处理,否则一旦报error错,如果不处理这个错误,程序就会崩溃
// error是个特别的事件,务必要处理的
// 报错就直接去重连
conn.on('error', (err) => {
log.error('connect_error ' + err.message, err)
reconnectRabbitMq()
})
// 创建channel
return conn.createChannel()
})
.then((ch) => {
CH = ch
// 初始化交换机
ch.assertExchange(ex, 'topic', {durable: true})
// 初始化一个队列,队列名就用hostName, 比较容易从对列名上知道是哪个实例创建的队列
return ch.assertQueue(hostName, queueAttr)
})
.then((q) => {
// 可以在队列初始化完毕就立即绑定routing key, 也可以暂时不绑定,后续动态的绑定
// CH.bindQueue(q.queue, ex, 'some.topic.aaa')
// 消费者,获取消息
CH.consume(q.queue, (msg) => {
var _msg = msg.content.toString()
var MSG = JSON.parse(_msg)
log.info(_msg, MSG)
}, {noAck: true})
})
.catch((err) => {
console.log(err)
})
}

动态给队列绑定或者解绑routing key


function toggleBindQueue (routingKey, bind) {
return new Promise((resolve, reject) => {
if (!CH) {
log.error('channel not established')
reject(new Error('channel not established'))
return ''
}
// 初始化队列,如果队列已经存在,就会直接使用
CH.assertQueue(`${hostName}`, queueAttr)
.then((q) => {
// 如果bind是true,就绑定。否则就解绑
if (bind) {
log.info(`bindQueue ${hostName} ${topic}`)
return CH.bindQueue(q.queue, ex, topic)
} else {
return CH.unbindQueue(q.queue, ex, topic)
}
})
.then((res) => {
resolve()
})
.catch((err) => {
reject(err)
log.error(err)
})
})
} module.exports = {
connectRabbitMq,
toggleBindQueue,
publishMessage
}

使用方法

加入你的服务端用的是Express, 那么在app.js中可以


...
const {connectRabbitMq} = require('./connect-mq.js')
connectRabbitMq()
...

完整代码


// onnect-mq.js
const amqp = require('amqplib')
// rabbitMQ地址
const {amqpAddrHost} = require('../config/index.js') // 交换机名称
const ex = 'amq.topic' const amqpAddr = `amqp://${amqpAddrHost}` // 读取HOSTNAME, 在跑多实例时,例如在k8s中,HOSTNAME可以获取当前pod的名称
// 多实例时,写日志,或者建立连接时,最好带上pod名称,如果出现问题,也比较好定位哪个pod出现的问题。
const hostName = process.env.HOSTNAME // 队列的属性设置
// 一般来说,最好设置队列自动删除autoDelete,当链接断开时,队列也会删除,这样不会产生非常多的无用队列
// durable是用来的持久化的,最好也可以设置成不持久化 const queueAttr = {autoDelete: true, durable: false} // 定义channel的引用,当链接建立时,所有方法都可以通过引用CH来获取channel方法
let CH = null // 向队列发送消息的函数
function publishMessage (msg) {
if (!CH) {
return ''
} msg = JSON.stringify(msg)
// 指定交换机ex, routing key, 以及消息的内容
CH.publish(ex, eventBusTopic, Buffer.from(msg))
} // 当链接rabbitMQ断开时,要主动去重连
function reconnectRabbitMq () {
log.info('reconnect_rabbit_mq')
connectRabbitMq()
} // 链接rabbitMQ的主要函数
function connectRabbitMq () {
amqp.connect(amqpAddr, {
// 设置connection_name的属性,可以在rabbitMQ的控制台的UI上,看到链接是来自哪个实例
clientProperties: {
connection_name: hostName
}
})
.then((conn) => {
log.info('rabbitmq_connect_successd')
// 一定要加上链接的报错事件处理,否则一旦报error错,如果不处理这个错误,程序就会崩溃
// error是个特别的事件,务必要处理的
// 报错就直接去重连
conn.on('error', (err) => {
log.error('connect_error ' + err.message, err)
reconnectRabbitMq()
})
// 创建channel
return conn.createChannel()
})
.then((ch) => {
CH = ch
// 初始化交换机
ch.assertExchange(ex, 'topic', {durable: true})
// 初始化一个队列,队列名就用hostName, 比较容易从对列名上知道是哪个实例创建的队列
return ch.assertQueue(hostName, queueAttr)
})
.then((q) => {
// 可以在队列初始化完毕就立即绑定routing key, 也可以暂时不绑定,后续动态的绑定
// CH.bindQueue(q.queue, ex, 'some.topic.aaa')
// 消费者,获取消息
CH.consume(q.queue, (msg) => {
var _msg = msg.content.toString()
var MSG = JSON.parse(_msg)
log.info(_msg, MSG)
}, {noAck: true})
})
.catch((err) => {
console.log(err)
})
} // 动态给队列绑定或者解绑routing key
function toggleBindQueue (routingKey, bind) {
return new Promise((resolve, reject) => {
if (!CH) {
log.error('channel not established')
reject(new Error('channel not established'))
return ''
}
// 初始化队列,如果队列已经存在,就会直接使用
CH.assertQueue(`${hostName}`, queueAttr)
.then((q) => {
// 如果bind是true,就绑定。否则就解绑
if (bind) {
log.info(`bindQueue ${hostName} ${topic}`)
return CH.bindQueue(q.queue, ex, topic)
} else {
return CH.unbindQueue(q.queue, ex, topic)
}
})
.then((res) => {
resolve()
})
.catch((err) => {
reject(err)
log.error(err)
})
})
} module.exports = {
connectRabbitMq,
toggleBindQueue,
publishMessage
}

来源:https://segmentfault.com/a/1190000016807727

Node.js连接RabbitMQ,断线重连,动态绑定routing key的更多相关文章

  1. Node.js使用rabbitMQ(一)

    目前使用的开发环境主要还是win,所以也只是介绍在win下的rabbitMQ的使用. 一.安装rabbitMQ(Installing on Windows) 关于安装地址,参见:Installing ...

  2. Node.js连接Mysql,并把连接集成进Express中间件中

    引言 在node.js连接mysql的过程,我们通常有两种连接方法,普通连接和连接池. 这两种方法较为常见,当我们使用express框架时还会选择使用中间express-myconnection,可以 ...

  3. Node.js 连接 MySQL 并进行数据库操作

    Node.js 连接 MySQL 并进行数据库操作  按照这篇操作mysql的指引,我远程操作了我另一台电脑的mysql数据库. var mysql = require('mysql'); var c ...

  4. Node.js连接MySQL数据库及构造JSON的正确姿势

    做一下整理,以前也很随意的引入包链接数据库,后来发现常常连接出问题,异常退出,后来使用在网上一个方法解决问题,网址由于书签丢失,抱歉不能引用了.再有就是简单的模块化下,使得目录合理点,再有就是说明一下 ...

  5. node.js连接MySQL操作及注意事项

    node.js作为服务端的js运行环境已经出现了有几年了,最近我有个朋友也在做这方面的开发,但是也是刚刚接触,遇到了很多坑.前几天他们在操作数据库的时候出现了点问题,后来我们一起看了看,其实都是nod ...

  6. 【js学习】js连接RabbitMQ达到实时消息推送

    js连接RabbitMQ达到实时消息推送 最近在自己捯饬一个网站,有一个功能是需要后端处理完数据把数据发布到MQ中,前端再从MQ中接收数据.但是前端连接MQ又成了一个问题,在网上搜了下资料,点进去一篇 ...

  7. Windows 7 下 Node.js 连接 Oracle

    原创作者: sailtseng 1. 安装 Oracle 11g express  详见: <Windows 7 x64 安装 Oracle 11g Express> 2. 安装 Micr ...

  8. windows下安装mongodb以及node.js连接mongodb

    一.MongoDB 下载 下载地址  https://www.mongodb.com/download-center#community  选择windows版下载,然后安装. 二.安装完毕后创建数据 ...

  9. node.js连接本地数据库及json返回数据

    新建一个文件夹node.js,目录下打开命令初始化一下 cnpm init 然后下载express框架 cnpm install express --save 接着下载数据库的依赖 cnpm inst ...

随机推荐

  1. Java+超大文件上传

    之前仿造uploadify写了一个HTML5版的文件上传插件,没看过的朋友可以点此先看一下~得到了不少朋友的好评,我自己也用在了项目中,不论是用户头像上传,还是各种媒体文件的上传,以及各种个性的业务需 ...

  2. ModelSerializer 使用知识点_序列化和反序列化用法区别

    1.ModelSerializer  如下 from api_test.errorCode.errorCode import Statusclass RelatedbSerializer(serial ...

  3. VMware NAT 静态IP模式下上网

    自从开始学Linux之后,对使用NAT模式上网,很是困惑.具体原理,还待求证. 使用方法(VMware): 简介: wmware在NAT使用方面很是轻松 打开本地的网络适配器. 修改虚拟网卡VMnet ...

  4. serlvet操作数据库

    工具:eclipse 数据库工具:mysql java ee操作数据库,首先要导入数据库驱动文件,我用的是mysql 刚开始,很多人代码正确但是就是连接不上,原因就是忘了驱动文件的导入. 我的驱动文件 ...

  5. hibernate一对一单项关联映射

    一.主键关联 1.两个实体对象的主键一样,以表明它们之间的一一对应关系: 2.不需要多余的外键字段来维护关系,仅通过主键来关联,即Person的主键要依赖IdCard的主键,他们共用一个主键值. Pe ...

  6. Linux_Comand - Check disk space

    df -h du -sh Delete folder older than 30 days find /path -name "test-*" -type d -mtime +30 ...

  7. Spring的Aop理解

    主要作用:解决代码复用,避免重复性编写代码. 比较典型的场景:日志打印,权限验证,事务处理 参考网址为:http://moon-walker.iteye.com/blog/2381532 spring ...

  8. leetcode-mid-dynamic programming-55. Jump Game

    mycode  71.47% 思路: 既然要到达终点,那么俺就可以倒推,要想到达n,可以有以下情况 1)到达n-1,然后该位置最少可以走一步 2)到达n-2,然后该位置最少可以走两步 3)到达n-3, ...

  9. c# SQLite 判断表、字段是否存在的方法,新增、删除、重命名列

    SQLiteHelper class: using System; using System.Collections.Generic; using System.Text; using System. ...

  10. TCP/IP 网络模型

    前言 互联网是怎么构成的,又是怎么运作的?什么是 TCP/IP 网络?为什么远隔万里的计算机可以互相通信?计算机网络作为 IT 行业的基石,是工程师永远绕不开的话题. 计算机网络的分层体系结构 计算机 ...