RabbitMQ学习(一)介绍

一、什么是RabbitMQ?

RabbitMQ是由Erlang语言编写的实现了高级消息队列协议(AMQP)的开源消息代理软件(也可称为 面向消息的中间件)。支持Windows、Linux/Unix、MAC OS X操做系统和包括JAVA在内的多种编程语言。编程

 

AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受 客户端/中间件 不一样产品,不一样的开发语言等条件的限制。浏览器

 

二、RabbitMQ中的重要概念

 

图片来源于网络安全

 

(1)Broker:经纪人。提供一种传输服务,维护一条从生产者到消费者的传输线路,保证消息数据能按照指定的方式传输。粗略的能够将图中的RabbitMQ Server看成Broker。服务器

(2)Exchange:消息交换机。指定消息按照什么规则路由到哪一个队列Queue。网络

(3)Queue:消息队列。消息的载体,每条消息都会被投送到一个或多个队列中。架构

(4)Binding:绑定。做用就是将Exchange和Queue按照某种路由规则绑定起来。负载均衡

(5)RoutingKey:路由关键字。Exchange根据RoutingKey进行消息投递。异步

(6)Vhost:虚拟主机。一个Broker能够有多个虚拟主机,用做不一样用户的权限分离。一个虚拟主机持有一组Exchange、Queue和Binding。编程语言

(7)Producer:消息生产者。主要将消息投递到对应的Exchange上面。通常是独立的程序。性能

(8)Consumer:消息消费者。消息的接收者,通常是独立的程序。

(9)Channel:消息通道,也称信道。在客户端的每一个链接里能够创建多个Channel,每一个Channel表明一个会话任务。

 

三、RabbitMQ的使用流程

AMQP模型中,消息在producer中产生,发送到MQ的exchange上,exchange根据配置的路由方式投递到相应的Queue上,Queue又将消息发送给已经在此Queue上注册的consumer,消息从queue到consumer有push和pull两种方式。

消息队列的使用过程大概以下:

(1)客户端链接到消息队列服务器,打开一个channel。

(2)客户端声明一个exchange,并设置相关属性。

(3)客户端声明一个queue,并设置相关属性。

(4)客户端使用routing key,在exchange和queue之间创建好Binding关系。

(5)生产者客户端投递消息到exchange。

(6)exchange接收到消息后,就根据消息的RoutingKey和已经设置的binding,进行消息路由(投递),将消息投递到一个或多个队列里。

(7)消费者客户端从对应的队列中获取并处理消息。

 

工做过程:

  • 生产者客户端:
  1. 客户端链接到RabbitMQ服务器上,打开一个消息通道(channel);
  2. 客户端声明一个消息交换机(exchange),并设置相关属性。
  3. 客户端声明一个消息队列(queue),并设置相关属性。
  4. 客户端使用routing key在消息交换机(exchange)和消息队列(queue)中创建好绑定关系。
  5. 客户端投递消息都消息交换机(exchange)上
  6. 客户端关闭消息通道(channel)以及和服务器的链接。
  • 服务器端:

exchange接收到消息后,根据消息的key(这个key的产生规则暂时没研究,有知道的小伙伴能够留言告诉我)和以及设置的binding,进行消息路由,将消息投递到一个或多个消息队列中。

关于exchange也有几个类型:

(1). Direct交换机:彻底根据key进行投递。例如,绑定时设置了routing key为abc,客户端提交信息提交信息时只有设置了key为abc的才会投递到队列;

(2).Topic交换机:在key进行模式匹配后进行投递。例如:符号”#”匹配一个或多个字符,符号”*”匹配一串连续的字母字符,例如”abc.#”能够匹配”abc.def.ghi”,而”abc.*”只能够匹配”abc.def”。

(3).Fanout交换机:它采起广播模式,消息进来时,将会被投递到与改交换机绑定的全部队列中。

  • 消费者客户端:待续...

 

四、RabbitMQ的消息持久化

 

RabbitMQ支持数据持久化,也就是把数据写在磁盘上,能够增长数据的安全性。消息队列持久化包括三个部分:

  1. 消息交换机(exchange)持久化,在声明时指定durable为1
  2. 消息队列(queue)持久化,在声明时指定durable为1
  3. 消息持久化,在投递时指定delivery_mode为2(1是非持久化)

若是消息交换机(exchange)和消息队列(queue)都是持久化的话,那么他们之间的绑定(Binding)也是持久化的。若是消息交换机和消息队列之间一个持久化、一个非持久化,那么就不容许绑定。

 

五、RabbitMQ的优缺点

适用场景

比较适合异步传输,这里解释一下什么是异步和同步。

异步:发送方不关心消息有没有发送成功,只发送消息,不去获取消息是否发送成功。

同步:发送方关心消息是否发送成功,发送消息后,会等待接收方返回状态码,根据状态码来判断是否发送成功,而后执行相对于的动做。

下边以Http中的同步和异步为例:

如:普通的B/S架构客户端和服务器端之间的通讯就是同步的,即提交请求 ---> 等待服务器处理完毕返回消息 ---> 拿到服务器返回的消息,处理完毕。

如:Ajax技术就是异步的,请求经过事件触发 ---> 服务器处理(浏览器不用等待,仍能够作其余的事情) ---> 处理完毕。

有人可能会好奇说应用场景怎么说到了同步和异步,那说明你还不是很理解技术和应用场景之间的紧密联系。

优势

(1)由Erlang语言开发,支持大量协议:AMQP、XMPP、SMTP、STOMP。

(2)支持消息的持久化负载均衡集群,且集群易扩展。

(3)具备一个Web监控界面,易于管理。

(4)安装部署简单,上手容易,功能丰富,强大的社区支持。

(5)支持消息确认机制、灵活的消息分发机制。

缺点

(1)因为牺牲了部分性能来换取稳定性,好比消息的持久化功能,使得RabbitMQ在大吞吐量性能方面不及Kafka和ZeroMQ。

(2)因为支持多种协议,使RabbitMQ很是重量级,比较适合企业级开发。

 

所以当须要一个稳定的、高可靠性的、功能强大且易于管理的消息队列能够选择RabbitMQ。若是对消息吞吐量需求较大,且不在意消息偶尔丢失的状况可使用Kafka。

六、Exchange类型

6.一、Direct Exchange

(1)名称:直接交换器类型

(2)默认的预先定义exchange名字:空字符串或者amq.direct

(3)做用描述:根据Binding指定的Routing Key,将符合Key的消息发送到Binding的Queue。能够构建点对点消息传输模型

 

图片源于网络

 

如图中RoutingKey分别是error、info、warning,其中error被Binding(绑定)到queue1和queue2上,info和warning被Binding到queue2上。当消息的RoutingKey是error,这条消息将被投递到queue1和queue2中(至关于消息被复制成两个分别投放到两个queue中),而后分别被Consumer1和Consumer2处理。若是消息的RoutingKey是info或者warning,这条消息只会被投递到queue2中,而后被Consumer2处理。若是消息的RoutingKey是其余的字符串,这条消息则会被丢弃。

6.二、Fanout Exchange

(1)名称:广播式交换器类型

(2)默认的预先定义exchange名字:amq.fanout

(3)做用描述:将同一个message发送到全部同该Exchange 绑定的queue。不论RoutingKey是什么,这条消息都会被投递到全部与此Exchange绑定的queue中。

图片来源于网络

 

广播式交换器类型的工做方式:不使用任何参数将queue和Exchange进行Binding,发布者publisher向Exchange发送一条消息(注意:直接交换器类型中的producer变成了publisher,其中隐含了两种交换器的区别),而后这条消息被无条件的投递给全部和这个Exchange绑定的queue中。

如图中,没有RoutingKey的限制,只要消息到达Exchange,都会被投递到queue1和queue2中,而后被对应的Consumer处理。

6.三、Topic Exchange

(1)名称:主题交换器类型

(2)默认的预先定义exchange名字:amq.topic

(3)做用描述:根据Binding指定的RoutingKey,Exchange对key进行模式匹配后投递到相应的Queue,模式匹配时符号“#”匹配一个或多个词,符号“*”匹配正好一个词,并且单词与单词之间必需要用“.”符号进行分隔。此模式能够用来支持经典的发布/订阅消息传输模型-使用主题名字空间做为消息寻址模式,将消息传递给那些部分或者所有匹配主题模式的queue。

图片来源于网络

 

    如图中,假如消息的RoutingKey是American.action.13,这条消息将被投递到Q1和Q2中。假如RoutingKey是American.action.13.test(注意:此处是四个词),这条消息将会被丢弃,由于没有routingkey与之匹配。假如RoutingKey是Chinese.action.13,这条消息将被投递到Q2和Q3中。假如RoutingKey是Chinese.action.13.test,这条消息只会被投递到Q3中,#能够匹配一个或者多个单词,而*只能匹配一个词。

6.四、Headers Exchange

(1)名称:标题交换器类型

(2)默认的预先定义exchange名字:amq.matchamq.headers

(3)做用描述:同direct exchange相似,不一样之处是再也不使用Routing Key路由,而是使用headers(Message attributes)进行匹配路由到指定Queue。

Headers类型的exchange使用的比较少,它也是忽略routingKey的一种路由方式。是使用Headers来匹配的。Headers是一个键值对,能够定义成HashTable。发送者在发送的时候定义一些键值对,接收者也能够再绑定时候传入一些键值对,二者匹配的话,则对应的队列就能够收到消息。匹配有两种方式all和any。这两种方式是在接收端必需要用键值"x-mactch"来定义。all表明定义的多个键值对都要知足,而any则代码只要知足一个就能够了。fanout,direct,topic exchange的routingKey都须要要字符串形式的,而headers exchange则没有这个要求,由于键值对的值能够是任何类型。