一、RabbitMQ作用及特点
1、作用(解耦、异步、消峰)
(1)、应用解耦(系统拆分)举例:购买一件商品,需要先支付,再扣减库存,但这两个操作必须是在同一事务中,即保证操作的原子性,但是这样做的话效率是极其低下的,如果使用RabbitMQ,只需要将消息发送给各自的队列来进行消息处理,支付和扣减库存的操作之间没有了关联性,这样支付系统和库存系统之间就进行了解耦。
(2)、异步处理(异步发送短信、推送消息、日志记录等)
(3)、流量削峰(缓冲队列):在访问量急剧增大的时候,RabbitMQ可以减少并发访问的压力,比较常见的业务场景就是秒杀和签到系统,一般来说流量的削峰有两个处理方式:a、上游队列缓冲,限速发送;b、下游队列缓冲,限速执行。常见的场景通常都采用第二种方式,为了不影响客户使用的响应速度和使用体验等。
(4)、消息分发
(5)、负载均衡
(6)、定时任务(延时队列)
(7)、顺序消费(消息队列)
2、特点
(1)、可靠性:RabbitMQ使用一些机制来保证可靠性,如数据持久化、传输确认及发布确认等。
(2)、灵活的路由:RabbitMQ提供了一些内置的交换器来实现。在消息进入队列之前,通过交换器来路由消息。针对更复杂的路由功能,可以将多个交换器绑定在一起,也可以通过插件机制来实现自己的交换器。
(3)、扩展性:多个RabbitMQ节点可以组成一个集群,也可以根据实际业务情况动态地扩展集群中节点。
(4)、高可用性:队列可以在集群中的机器上设置镜像,使得在部分节点出现问题的情况下队仍然可用。
(5)、多种协议:RabbitMQ除了原生支持AMQP协议,还支持STOMP,MQTT等多种消息中间件协议。
(6)、多语言客户端:RabbitMQ几乎支持所有常用语言,比如Java、Python、Ruby、PHP、C#、JavaScript等。
(7)、管理界面:RabbitMQ提供了一个易用的用户界面,使得用户可以监控和管理消息、集群中的节点等。
(8)、插件机制:RabbitMQ提供了许多插件,以实现从多方面进行扩展,当然也可以编写自己的插件。
二、消息传输原理
由于TCP链接的创建和销毁开销较大,且并发数受系统资源限制,会造成性能瓶颈,所以RabbitMQ使用信道的方式来传输数据。信道(Channel)是生产者、消费者与RabbitMQ通信的渠道,信道是建立在TCP链接上的虚拟链接,且每条TCP链接上的信道数量没有限制。就是说RabbitMQ在一条TCP链接上建立成百上千个信道来达到多个线程处理,这个TCP被多个线程共享,每个信道在RabbitMQ都有唯一的ID,保证了信道私有性,每个信道对应一个线程使用。
三、AMQP(高级消息队列协议)
1、基本概念
Broker:接收和分发消息的应用。
Virtual host:出于多租户和安全因素设计的,把AMQP的基本组件划分到一个虚拟的分组中,类似于网络中的nameSpace概念。当多个不同的用户使用同一个RabbitMQ server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue等。
Connection:publisher/consumer和broker之间的TCP连接。
Channel:Channel是在TCP connection内部建立的逻辑连接,多线程情况下每个thread创建单独的channel进行通讯,AMQP method包含了channel id帮助客户端和Broker识别channel,所以channel之间是完全隔离的。
Queue:消息最终被送到队列等待consumer取走,一个message可以被同时拷贝到多个queue中。
Binding:exchange和queue之间的虚拟连接,binding中可以包含routing key。Binding信息被保存到exchange中的查询表中,用于message的分发依据。
Exchange:message到达Broker的第一站,根据分发规则,匹配查询表中的routing key,分发消息到queue中去。包含四种类型:
a、fanout:把所有发送到该Exchange的消息路由到所有与它绑定的Queue中,与routingKey无关。
b、direct:把消息路由到那些binding key与routing key完全匹配的Queue中。
c、topic:将消息路由到binding key与routing key相匹配的Queue中,但这里的匹配规则有些不同,它约定:
routing key为一个句点号“.”分隔的字符串(我们将被句点号“.”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”
binding key与routing key一样也是句点号“.”分隔的字符串
binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)
d、headers:根据发送的消息内容中的headers属性进行匹配。在绑定Queue与Exchange时指定一组键值对;当消息发送到Exchange时,RabbitMQ会取到该消息的headers(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对;如果完全匹配则消息会路由到该Queue,否则不会路由到该Queue。很少用。
Routing key:生产者在将消息发送给Exchange的时候,一般会指定一个routing key,来指定这个消息的路由规则。
Binding key:在绑定(Binding)Exchange与Queue的同时,一般会指定一个binding key。当binding key与routing key相匹配时,消息才会被路由到对应的Queue中。