写在前面
在我们的生产环境中搭了两台rabbitmq, 前面架设了一台HAProxy做负载均衡,当我们的客户端连接到HAProxy,然后由HAProxy负责将链接分配给其中一台rabbitmq,客户端需要需要负责断线重连,需要将获取的数据,分配消息给相应的处理方法,然后还需要回复给rabbitmq ACK,这其中客户端需要负责断线重连的逻辑是很重要的,因为有可能客户端和HAProxy的连接是正常的,但是HAProxy和rabbitmq的链接因为网络波动断开了,那么这个时候客户端其实是没有工作的,并且会在rabbitmq中不断积累消息。
下面的内容给出了一个比较完善的处理逻辑,以供参考。
实战
定义接口
从之前的说明来看,这是一个典型的观察者模式,由RabbitMQ对象负责维护连接,获取消息,然后定义若干个接收者注册到RabbitMQ对象中,这时候RabbitMQ对象一旦收到了由RabbitMQ发来的数据,就可以将该消息分发到相应的接收者去处理,当接收者处理完成后告诉RabbitMQ对象消息消费成功,然后由RabbitMQ对象回复RabbitMQ ACK,当然可以在其中加上重试机制,接收者有可能因为某种情况处理失败,那么每隔一定的时间RabbitMQ对象需要重新调用一次接收者重新处理,直至成功,然后再返回ACK。
先来看看基本的接口约定
// Receiver 观察者模式需要的接口
// 观察者用于接收指定的queue到来的数据
type Receiver interface {
QueueName() string // 获取接收者需要监听的队列
RouterKey() string // 这个队列绑定的路由
OnError(error) // 处理遇到的错误,当RabbitMQ对象发生了错误,他需要告诉接收者处理错误
OnReceive([]byte) bool // 处理收到的消息, 这里需要告知RabbitMQ对象消息是否处理成功
}
这样就将接收者和RabbitMQ对象之间就解耦了,这样后期如果需要添加新的接收者那就很容易了。
下面来看一看RabbitMQ对象的定义:
这里用到的RabbitMQ client是RabbitMQ官方的 Github
// RabbitMQ 用于管理和维护rabbitmq的对象
type RabbitMQ struct {
wg sync.WaitGroup
channel *amqp.Channel
exchangeName string // exchange的名称
exchangeType string // exchange的类型
receivers []Receiver
}
// New 创建一个新的操作RabbitMQ的对象
func New() *RabbitMQ {
// 这里可以根据自己的需要去定义
return &RabbitMQ{
exchangeName: ExchangeName,
exchangeType: ExchangeType,
}
}