上一篇记录了一下AMQP协议,RabbitMQ是一个Erlang
开发的AMQP协议
的开源实现。这一篇简单的介绍一下RabbitMQ的基本原理。
一、RabbitMQ的特点
1、可靠性:RabbitMQ可以通过持久化、传输确认及发布确认来保证可靠性。
2、扩展性:多个RabbitMQ节点可以组成一个集群,也可以根据实际业务情况动态地扩展集群中节点。
3、多种协议:RabbitMQ除了原生支持AMQP协议,还支持STOMP,MQTT等多种消息中间件协议。
4、管理界面:RabbitMQ提供了一个易用的用户界面,使得用户可以监控和管理消息、集群中的节点。
5、多语言客户端:RabbitMQ几乎支持所有常用语言,比如Jav a、Python、Ruby、PHP、C#、JavaScript。
二、RabbitMQ的优点
1、 解耦:Rabbitmq中间件减少了应用程序之间的强依赖,举个例子:电商后台要删除某个产品,除了要delete数据库数据,还要通知CMS,如果通知CMS的操作使用RabbitMQ那么,电商后台删除产品的应用程序就不需要等待CMS响应。
2、存储:消息中间件支持数据持久化。如果通知CMS失败,那么通知信息会被持久化,直到能够通知到CMS为止。
3、扩展性:消息中间件解耦了应用的过程,所以提供消息入队和处理的效率是很容易的,只需要增加处理流程就可以了。 4、削峰:对于突发的大访问压力,使用消息中间件采用队列的形式可以减少突发访问压力,不会因为突发的超时负荷要求而崩溃。 5、可恢复性:消息中间件降低了进程间的耦合性,当一个处理消息的进程挂掉后,加入消息中间件的消息仍然可以在系统恢复后重新处理 6、顺序保证:RabbitMQ就是消息队列的实现,消息队列的特点就是先进先出,所以有顺序保证。7、异步通信:通过把把消息发送给消息中间件,消息中间件并不立即处理它,后续在慢慢处理。
三、RabbitMQ的原理
1、RabbitMQ中设计的名词解释
(1)Producer(生产者):生产者和消费者都是RabbitMQ的客户端,生产者就是为了生产消息。
(2)Consumer(消费者):生产者和消费者都是RabbitMQ的客户端,消费者就是数据的接收方,消费者从queue中取数据。
(3)Broker:RabbbitMQ消息队列代理服务器实体。
(4)Vhost(虚拟主机):一个Broker里可以开设多个vhost,用作不同用户的权限分离。
(5)Message:传输的消息体,由payload和label组成,payload是传输的消息数据,label是exchange的名字,作为tag。
(6)Exchanges:Producer发送的消息会通过Exchange根据相应的规则分发到queue。
(7)Binding(绑定):指定交换器和队列之间的关系,就是把exchange和queue按照路由规则绑定起来。
(8)Queue:用来存储消息的地方,由Consumer进行消费,消费之后queue的这个消息就被删除掉了。
(9)Routing Key(路由关键字):exchange根据Routing Key将消息投放到相应队列。
(10)Connection:Producer和Consumer这两个客户端都是通过TCP连接到某个虚拟主机。
(11)Channel(消息通道):包含了大量的API可用于编程。在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。也就是说,一般情况是程序起始建立TCP连接,第二步就是建立这个Channel。目的是保持长连接,减少tcp创建的性能损耗。
(12)ConnectionFactory:连接工厂类,可以创建一个连接。
(13)Acknowledged(ack):Consumer将消息消费完毕后给server的回执确认,Server确认后会把消息从queue中删除。
(14)Direct:Exchange的一种类型,如果 routing key 匹配, 那么Message就会被传递到相应的queue中。
(15)Fanout: Exchange的一种类型,所有与exchange关联的queue都会被传递。
(16)Topic: Exchange的一种类型,按照routingkey规则匹配的queue 。
2、RabbitMQ流程图(来自于百度图片)
3、RabbitMQ原理描述
假设Producer1和Consumer1注册了相同的Broker,Exchange和Queue。Producer1发送的消息最终会被Consumer1消费。基本的通信流程如下:
(1)Producer1生产消息,发送给服务器端的Exchange
(2)Exchange收到消息,根据Routing Key,将消息转发给匹配的Queue1
- (3)Queue1收到消息,将消息发送给订阅者Consumer1
- (4)Consumer1收到消息,发送ACK给队列确认收到消息
- (5)Queue1收到ACK,删除队列中缓存的此条消息
4、注意事项
Consumer收到消息时需要显式的向Rabbit Broker发送ack消息或者Consumer订阅消息时设置auto_ack参数为true。在通信过程中,队列对ACK的处理有以下几种情况:
(1)如果Consumer接收了消息,发送ack,Rabbitmq会删除队列中这个消息,发送另一条消息给Consumer。
(2)如果Cosumer接受了消息, 但在发送ack之前断开连接,Rabbitmq会认为这条消息没有被Deliver,在Consumer在次连接的时候,这条消息会被Redeliver。
(3)如果Consumer接受了消息,但是程序中有Bug,忘记了ack,Rabbitmq不会重复发送消息。
(4)Rabbitmq2.0.0和之后的版本支持Consumer通过设置Requeue参数中的reject为true 拒绝某条消息,那么Rabbitmq将会把消息发送给下一个注册的Consumer。
四、RabbitMQ的应用场景
RabbitMQ的集中典型应用可以参考