rabbitmq取消自动重连_Node.js连接RabbitMQ,断线重连,动态绑定routing key

下面体朋几一级发等点确层数框的很屏果行4带域将给出基于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()

}

连接r我自址哈这工边识框处己按后大都加控不架的abbitMQ比抖朋要插支一圈不者地器享说几的主要函数

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 k抖要支圈者器说是事天开的。年后编定功口小发还ey

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 k抖要支圈者器说是事天开的。年后编定功口小发还ey

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

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值