以下内容转载自https://www.jianshu.com/p/5c2d8af2c78e
RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据,或者简单的将作业排队以便让分布式服务器进行处理。
AMQP
,即Advanced Message Queuing Protocol
,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。消息中间件主要用于组件之间的解耦,消息的发送者无需知道消息使用者的存在,反之亦然。
AMQP
的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。
RabbitMQ
是一个开源的AMQP
实现,服务器端用Erlang
语言编写,支持多种客户端,如:Python、Ruby、.NET、Java、JMS、C、PHP、ActionScript、XMPP、STOMP等,支持AJAX
,最重要的是也支持OC和swift
。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。
producer
表示消息的生产者
,用来创建消息,然后发布到代理服务器(RabbitMQ)
。消息包括有效载荷
和标签
,
consumer
是消息的接受者
,比如各种的客户端
queue
就像一个RabbitMQ的信箱
,是AMQP
消息通信的基础模块。
queue
为消息提供处所,消息在此等待消费。
queue
对负载均衡来说,队列是绝佳方案。只需要附加一堆消费者,并让RabbitMQ以循环的方式均匀地分配发来的消息。
queue
只受主机内存和磁盘的限制,它的本质是一个巨大的消息缓冲区。producer可以向queue发送消息,consumers也可以从queue接收消息。
多个消费者
可以订阅同一个queue
,这时queue中的消息会被平均分摊给多个消费者进行处理,而不是每个消费者都收到所有的消息并处理。
ConnectionFactory、Connection、Channel
都是RabbitMQ对外提供的API中最基本的对象。
Connection
是RabbitMQ的socket链接,它封装了socket协议相关部分逻辑。ConnectionFactory
为Connection的制造工厂。Channel
是我们与RabbitMQ打交道的最重要的一个接口,我们大部分的业务操作是在Channel这个接口中完成的,包括定义Queue、定义Exchange、绑定Queue与Exchange、发布消息等。如果我们希望即使在RabbitMQ
服务重启的情况下,也不会丢失消息,我们可以将Queue
与Message
都设置为可持久化的(durable
),这样可以保证绝大部分情况下我们的RabbitMQ
消息不会丢失。但依然解决不了小概率丢失事件的发生(比如RabbitMQ
服务器已经接收到生产者的消息,但还没来得及持久化该消息时RabbitMQ
服务器就断电了),如果我们需要对这种小概率事件也要管理起来,那么我们要用到事务。由于这里仅为RabbitMQ
的简单介绍,所以这里将不讲解RabbitMQ
相关的事务。
实际的情况是,生产者将消息发送到Exchange(交换机,下图中的X)
,由Exchange
将消息路由到一个或多个Queue
中(或者丢弃)。
生产者
在将消息
发送给Exchange
的时候,一般会指定一个routing key(当然也可以不指定)
,来指定这个消息的路由规则
,而这个routing key
需要与Exchange Type
及binding key
联合使用才能最终生效。
在Exchange Type
与binding key
固定的情况下,我们的生产者
就可以在发送消息给Exchange
时,通过指定routing key来决定消息流向哪里
。RabbitMQ
为routing key
设定的长度限制为255 bytes。
RabbitMQ
中通过Binding
将Exchange与Queue关联起来
,这样RabbitMQ
就知道如何正确地将消息路由到指定的Queue
了。
在绑定(Binding)Exchange与Queue
的同时,一般会指定一个binding key
;消费者将消息发送给Exchange
时,一般会指定一个routing key
;当binding key与routing key
相匹配时,消息将会被路由到对应的Queue中。
在绑定多个Queue
到同一个Exchange
的时候,这些Binding
允许使用相同的binding key
。
binding key
并不是在所有情况下都生效,它依赖于Exchange Type
,比如fanout类型
的Exchange
就会无视binding key
,而是将消息路由到所有绑定到该Exchange的Queue
。
RabbitMQ
常用的Exchange Type
有fanout、direct、topic、headers
这四种(AMQP规范里还提到两种Exchange Type,分别为system与自定义,这里不予以描述),下面分别进行介绍。
fanout类型
的Exchange路由规则
非常简单,它会把所有发送到该Exchange
的消息路由到所有与它绑定的Queue
中。
direct类型
的Exchange
路由规则也很简单,它会把消息路由到那些binding key与routing key
完全匹配的Queue
中。
例如,我们以routingKey=”error”
发送消息到Exchange
,则消息会路由到Queue1
(amqp.gen-S9b…,这是由RabbitMQ自动生成的Queue名称)和Queue2
(amqp.gen-Agl…);如果我们以routingKey=”info”
或routingKey=”warning”
来发送消息,则消息只会路由到Queue2
。如果我们以其他routingKey
发送消息,则消息不会路由到这两个Queue
中。
前面讲到direct类型
的Exchange
路由规则是完全匹配binding key
与routing key
,但这种严格的匹配方式在很多情况下不能满足实际业务需求。topic类型
的Exchange
在匹配规则上进行了扩展,它与direct
类型的Exchage
相似,也是将消息路由到binding key
与routing key
相匹配的Queue
中,但这里的匹配规则有些不同,它约定:
routing key
为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”
binding key
与routing key
一样也是句点号“. ”分隔的字符串binding key
中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”
用于匹配一个单词,“#”
用于匹配多个单词(可以是零个)routingKey=”quick.orange.rabbit”
的消息会同时路由到Q1与Q2,routingKey=”lazy.orange.fox”
的消息会路由到Q1,routingKey=”lazy.brown.fox”
的消息会路由到Q2,routingKey=”lazy.pink.rabbit”
的消息会路由到Q2(只会投递给Q2一次,虽然这个routingKey
与Q2的两个bindingKey
都匹配);routingKey=”quick.brown.fox”
、routingKey=”orange”
、routingKey=”quick.orange.male.rabbit”
的消息将会被丢弃,因为它们没有匹配任何bindingKey
。headers
类型的Exchange
不依赖于routing key
与binding key
的匹配规则来路由消息,而是根据发送的消息内容中的headers
属性进行匹配。
在绑定Queue
与Exchange
时指定一组键值对;当消息发送到Exchange
时,RabbitMQ
会取到该消息的headers
(也是一个键值对的形式),对比其中的键值对是否完全匹配Queue
与Exchange
绑定时指定的键值对;如果完全匹配则消息会路由到该Queue
,否则不会路由到该Queue
。
该类型的Exchange
没有用到过(不过也应该很有用武之地),所以不做介绍。