最近在给自己的服务进行解耦,就需要用到消息队列,虽然Redis能够实现消息队列,但是对于实时性要求没有太高,于是就想到了各种MQ产品,目前市面上有很多,比如ActiveMQ,RabbitMQ,Kafka,ZeroMQ,RocketMQ等等。
对比了一下各家的MQ产品,最终看中了RabbitMQ。RabbitMQ是用Erlang作为开发语言进行开发的开源消息队列,所以在使用RabbitMQ之前,得先配好Erlang的环境,当然本身支持很多协议包括:AMQP,XMPP,SMTP等。
一、三个角色
对于MQ产品而言,一般包含三种角色:
- 生产者(Producer)
- 队列(queue)
- 消费者(consumer)
一个大致的流程就是生产者产生消息,消息包括两个部分:有效载荷(payload)和标签(label),并将消息放入队列中,这个时候生产者的任务就完成了,队列服务器会根据标签信息发送给对应的消费者,等待消费者去消费就行了,当消费者消费消息的时候只会得到消息的有效载荷。
另外生产者、队列以及消费者可以不放在同一台机器上,在某种程度上也是一种解耦。
二、信道
在消费者或者生产者与RabbitMQ服务器之间除了创建了一条TCP连接,还需要在这条连接上建立一条虚拟的信道(channel),每一条信道都会有被指派一个唯一ID保存在服务器上,所有的发送、传送和接收消息都是在这条信道上完成的。
这样做的好处就是在消息量大的时候,相对于每一个线程创建一个TCP连接,信道的模式能够减少创建TCP连接带来的开销,保障了时效性。
三、消息确认
为了保障消息队列的可靠性,MQ产品设计了一个消息消费确认机制,当生产者将消息放在队列上等待消费者消费时,消费者每接收到一条消息,都必须进行确认,这里有两种情况,一种是手动确认,一种是自动确认。
- 手动确认是指当消费者接收到消息时,显示地向RabbitMQ服务发送一个确认,这样做的好处是,当应用程序有BUG忘记确认消息或者出现格式错误导致无法处理而崩溃时,RabbitMQ则不会继续发送更多的消息给消费者,防止消息的丢失
- 自动确认是指一旦消费者接收到消息之后,RabbitMQ服务器将会自动确认已经正确接收到消息了,这样做对于一些简单的消息来说,提高了效率。
- 当然如果程序出现问题时也可以主动拒收消息,这个时候消费者可以向RabbitMQ服务器发送一个reject命令,当服务器接收到后会将这条信息放入“死信”(dead letter)队列,这个队列专门存放那些被拒绝又不重新入队的消息,这样通过监控死信队列可以及时发现问题。
四、几种工作模式
1. 简单队列
一个生产者,一条队列,一个消费者。
2. Work模式
两个消费者,一条消息只能被一个消费者消费,分摊消费压力,有点负载均衡的意思。
3. 发布/订阅模式
可以有多个消费者,而每个消费者都有自己的队列,每个队列要绑定到交换器,发送者将消息交给交换器,交换器根据绑定时指定的binding key,将消息放进对应的队列
交换器有4种类型:
- direct
- fanout
- topic
- headers
4. 路由模式
交换器为direct,交换器根据不同的路由键(routing key),放进不同的队列中,可以有个路由键对应同一条队列

5. 主题模式
主题模式也就是通配符模式。同一个消息被多个消费者获取。一个消费者队列可以有多个消费者实例,只有其中一个消费者实例会消费到消息。