RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol (AMQP)的开源实现,由以高性能、健壮以及可伸缩性出名的 Erlang 写成(所以也是继承了这些优势)。安全
首先介绍 AMQP 和一些基本概念:服务器
当前各类应用大量使用异步消息模型,并随之产生众多消息中间件产品及协议,标准的不一导致应用与中间件之间的耦合限制产品的选择,并增长维护成本。 AMQP 是一个提供统一消息服务的应用层标准协议,基于此协议的客户端与消息中间件可传递消息,并不受客户端 / 中间件不一样产品,不一样开发语言等条件的限制。 固然这种下降耦合的机制是基于与上层产品,语言无关的协议。 AMQP 协议是一种二进制协议,提供客户端应用与消息中间件之间异步、安全、高效地交互。从总体来看, AMQP 协议可划分为三层。网络
这种分层架构相似于 OSI 网络协议,可替换各层实现而不影响与其它层的交互。AMQP 定义了合适的服务器端域模型,用于规范服务器的行为 (AMQP 服务器端可称为 broker) 。架构
Model 层决定这些基本域模型所产生的行为,这种行为在 AMQP 中用 ”command”表示,在后文中会着重来分析这些域模型。异步
Session 层定义客户端与 broker 之间的通讯 ( 通讯双方都是一个 peer ,可互称作partner) ,为 command 的可靠传输提供保障。ide
Transport 层专一于数据传送,并与 Session 保持交互,接受上层的数据,组装成二进制流,传送到 receiver 后再解析数据,交付给 Session 层。 Session 层须要Transport 层完成网络异常状况的汇报,顺序传送 command 等工做。性能
AMQP 当中有四个概念很是重要:虚拟主机( virtual host ),交换机( exchange),队列( queue )和绑定( binding )。ui
虚拟主机( virtual host ):一个虚拟主机持有一组交换机、队列和绑定。为何须要多个虚拟主机呢? RabbitMQ 当中,用户只能在虚拟主机的粒度进行权限控制。所以,若是须要禁止 A 组访问 B 组的交换机 / 队列 / 绑定,必须为 A 和 B 分别建立一个虚拟主机。每个 RabbitMQ 服务器都有一个默认的虚拟主机 “/” 。spa
队列( Queue ):由消费者创建的,是 messages 的终点,能够理解成装消息的容器。消息一直存在队列里,直到有客户端或者称为 Consumer 消费者链接到这个队列并将 message 取走为止。队列能够有多个。orm
交换机( Exchange ):能够理解成具备路由表的路由程序。每一个消息都有一个路由键( routing key ),就是一个简单的字符串。交换机中有一系列的绑定( binding),即路由规则( routes )。交换机能够有多个。多个队列能够和同一个交换机绑定,同时多个交换机也能够和同一个队列绑定。(多对多的关系)
三种交换机:
1. Fanout Exchange (不处理路由键):一个发送到交换机上的消息都会被转发到与该交换机绑定的全部队列上。 Fanout 交换机发消息是最快的。
2. Direct Exchange (处理路由键):若是一个队列绑定到该交换机上,而且当前要求路由键为 X ,只有路由键是 X 的消息才会被这个队列转发。
3. Topic Exchange (将路由键和某模式进行匹配,能够理解成模糊处理):路由键的词由 “.” 隔开,符号 “#” 表示匹配 0 个或多个词,符号 “*” 表示匹配很少很多一个词。所以 “ audit.# ” 可以匹配到 “ audit.irs.corporate ” ,可是 “ audit.* ” 只会匹配到 “ audit.irs ”
具体例子能够看下图
持久化:队列和交换机有一个建立时候指定的标志durable,直译叫作坚固的。durable的惟一含义就是具备这个标志的队列和交换机会在重启以后从新创建,它不表示说在队列当中的消息会在重启后恢复。那么如何才能作到不仅是队列和交换机,还有消息都是持久的呢?
可是首先一个问题是,你真的须要消息是持久的吗?对于一个须要在重启以后回复的消息来讲,它须要被写入到磁盘上,而即便是最简单的磁盘操做也是要消耗时间的。若是和消息的内容相比,你更看重的是消息处理的速度,那么不要使用持久化的消息。
当你将消息发布到交换机的时候,能够指定一个标志“Delivery Mode”(投递模式)。根据你使用的AMQP的库不一样,指定这个标志的方法可能不太同样。简单的说,就是将 Delivery Mode设置成2,也就是持久的便可。通常的AMQP库都是将Delivery Mode设置成1,也就是非持久的。因此要持久化消息的步骤以下:
1. 将交换机设成 durable 。
2. 将队列设成 durable 。
3. 将消息的 Delivery Mode 设置成 2 。
绑定( Bindings )如何持久化?咱们没法在建立绑定的时候设置成 durable 。没问题,若是绑定了一个 durable 的队列和一个 durable 的交换机, RabbitMQ 会自动保留这个绑定。相似的,若是删除了某个队列或交换机(不管是否是 durable ),依赖它的绑定都会自动删除。
注意两点:
1. RabbitMQ 不容许绑定一个非坚固( non-durable )的交换机和一个 durable 的队列。反之亦然。要想成功必须队列和交换机都是 durable 的。
2. 一旦建立了队列和交换机,就不能修改其标志了。例如,若是建立了一个 non-durable 的队列,而后想把它改变成 durable 的,惟一的办法就是删除这个队列而后重现建立。所以,最好仔细检查建立的标志。
几个概念说明:
1. Broker:简单来讲就是消息队列服务器实体。
2. Exchange:消息交换机,它指定消息按什么规则,路由到哪一个队列。
3. Queue:消息队列载体,每一个消息都会被投入到一个或多个队列。
4. Binding:绑定,它的做用就是把exchange和queue按照路由规则绑定起来。
5. Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
6. vhost:虚拟主机,一个broker里能够开设多个vhost,用做不一样用户的权限分离。
7. producer:消息生产者,就是投递消息的程序。
8. consumer:消息消费者,就是接受消息的程序。
9. channel:消息通道,在客户端的每一个链接里,可创建多个channel,每一个channel表明一个会话任务。
消息队列的使用过程大概以下:
1. 客户端链接到消息队列服务器,打开一个channel。
2. 客户端声明一个exchange,并设置相关属性。
3. 客户端声明一个queue,并设置相关属性。
4. 客户端使用routing key,在exchange和queue之间创建好绑定关系。
5. 客户端投递消息到exchange。
6. exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。