一、什么是消息队列?
消息队列(MessageQueue),简称MQ,FIFO,即先进先出,是一种为了解决“逻辑解耦+物理解耦”的消息通信服务。
MQ是一种系统间相互协作的通信机制, 在系统解耦、流量削峰、日志收集、保持事务一致性等方便都会有很大帮助,一个典型的消息队列,如下图所示:
- Broker:消息处理中心,负责消息的接受、存储、转发;
- Producer:消息生产者,负责产生和发送消息到消息处理中心;
- Consumer:消息消费者,负责从消息处理中心获取消息,并进行相应的处理;
二、什么是AMQP?
AMQP(Advanced Message Queue Protocol)是一种用于实现消息队列所涉及的协议,常见的协议有AMQP、MQTT、STOMP、XMPP等。RabbitMQ是一个由erlang开发的AMQP的开源实现。官网地址:RabbitMQ官网地址
先了解一下AMQP协议的基本概念:
-
Message(消息):消息服务器处理数据的原子单元。消息包括一个内容头、一组属性和一个内容体。消息可以被存储到硬盘中,本身有优先级;
-
Publisher(消息生产者):一个向交换器发布消息的客户端应用程序;
-
Broker(消息代理): 接收和分发消息的应用,RabbitMQ Server就是Message Broker,实现消息队列和路由功能的过程
-
Consumer(消息消费者):一个从消息队列中取得消息的客户端用用程序
-
Exchange(交换器): Message到达Broker的第一站,根据分发规则,匹配查询表中的 Routing key,分发消息到Queue中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast),详解见第三部分。
-
Binding(绑定): 用于消息队列和交换器之间的关联,binding中可以包含routing key。交换器就是一个由绑定构成的路由表
-
Virtual host(虚拟主机): 出于多租户和安全因素设计的,把AMQP的基本组件划分到一个虚拟的分组中,类似于网络中的namespace概念。当多个不同的用户使用同一个RabbitMQ server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue等,每一个虚拟主机本质上是一个mini版的消息服务器。
-
Routing key(路由规则):虚拟机使用它来确定如何路由一个特定的消息
-
Connection(连接): publisher/consumer和broker之间的TCP连接。断开连接的操作只会在client端进行,Broker不会断开连接,除非出现网络故障或broker服务出现问题。
-
Channel(信道): 如果每一次访问RabbitMQ都建立一个Connection,在消息量大的时候建立TCP Connection的开销将是巨大的,效率也较低。Channel是在connection内部建立的逻辑连接,信道是一条独立的双向数据流通道,是建立在真实的TCP连接内的虚拟连接,一个connection可以包含多条信道;Channel作为轻量级的Connection极大减少了操作系统建立TCP connection的开销。
-
Queue(消息队列): 用来保存消息,等待consumer取走。一个message可以被同时拷贝到多个queue中。
AMQP的生命周期:
Publisher产生一条消息,发送到Broker,broker中的Exchange可以被理解为一个规则表,Broker收到消息以后根据Routing key查询投递目标queue,Consumer向Broker订阅消息时,会指定自己监听那个Queue,当有数据到达Queue时,Broker会推送数据到Consumer。
三、交换器类型
在AMQP生命周期图中,生产者产生的消息并不是直接发送给消息队列Queue的,而是要经过Exchange(交换器),由Exchange再将消息路由到一个或多个Queue,当然这里还会对不符合路由规则的消息进行丢弃掉,这里指的是后续要谈到的Exchange Type。
那么Exchange是怎样将消息准确的推送到对应的Queue的呢?那么这里的功劳最大的当Binding,RabbitMQ是通过Binding将Exchange和Queue链接在一起,这样Exchange就知道如何将消息准确的推送到Queue中去。
不同类型的交换器分发消息的策略是不同的,目前交换器有4种类型:Direct、Fanout、Topic、Headers,其中Headers交换器匹配AMQP消息的header而不是路由键,目前几乎不用了,所以我们来看一下另外三种交换器。
3.1-Direct
direct类型的Exchange路由规则很简单,它会把消息路由到那些binding key与routing key完全匹配的Queue中,路由键要和队列名称要完全匹配(并不是名字一样)Direct交换器是完全匹配、单播的模式。
3.2-Fanout
fanout类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中。这很像子网广播,子网内的每个主机都会获得一份复制的消息。
3.3-Topic
相对于Direct交换器,Topic交换器就是模糊查询。binding key中可以存在两种特殊字符“”与“#”,用于做模糊匹配,其中“”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)
在RabbitMQ默认定义一些交换机,主要如下:
3.4-默认交换机
RabbitMQ默认定义一些交换机
默认交换机(default exchange)实际上是一个由RabbitMQ预先声明好的名字为空字符串的直连交换机(direct exchange)。它有一个特殊的属性使得它对于简单应用特别有用处:那就是每个新建队列(queue)都会自动绑定到默认交换机上,绑定的路由键(routing key)名称与队列名称相同。
如:当你声明了一个名为”test”的队列,RabbitMQ会自动将其绑定到默认交换机上,绑定(binding)的路由键名称也是为”test”。因此,当消息(路由键为”test”)被发送到默认交换机时,此消息会被默认交换机路由至名为”test”的queue中。
如图,类似amq.*的名称的交换机是RabbitMQ默认创建的交换机。这些队列名称被预留做RabbitMQ内部使用,不能被应用使用,否则抛出403 (ACCESS_REFUSED)错误。
四、RabbitMQ安装(linux)
因为RabbitMQ是基于Erlang的,所以要先安装Erlang环境
1.安装Erlang
yum install erlang
验证命令:erl 出现如图结果表示安装erlang成功
2.安装RabbitMQ
先下载rpm:
wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.6/rabbitmq-server-3.6.6-1.el7.noarch.rpm
rpm -ivh rabbitmq-server-3.5.0-1.noarch.rpm
--启动rabbitmq,并验证启动情况
rabbitmq-server --detached &ps aux |grep rabbitmq
--开启相关端口
--4369 (epmd)
--25672 (Erlang distribution)
--5672, 5671 (AMQP 0-9-1 without and with TLS)
--15672 (if management plugin is enabled)
/sbin/iptables -I INPUT -p tcp --dport 4369 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 25672 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 5671 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 5672 -j ACCEPT
/sbin/iptables -I INPUT -p tcp --dport 15672 -j ACCEPT
/etc/rc.d/init.d/iptables save
/etc/init.d/iptables restart
/etc/init.d/iptables status
--开启管理后台模块
rabbitmq-plugins enable rabbitmq_management
浏览器登录,如图所示,安装成功。
五、FAQ
关于消息队列的详细可以参考:
推荐书籍《RabbitMQ实战》