一、RabbitMQ简介
RabbitMQ是一个由erlang语言编写的、开源的、在AMQP基础上完整的、可复用的企业消息系统。支持多种语言,包括java、Python、ruby、PHP、C/C++等。
- MQ:message queue 的简称,即消息队列,是应用程序和应用程序之间通信的中间件。
- AMQP:advanced message queuing protocol ,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息并不受客户端/中间件不同产品、不同开发语言等条件的限制。
二、RabbitMQ的核心概念
RabbitMQ基础架构如下:
- Broker:接收和分发消息的应用,RabbitMQ Server就是 Message Broker
- Virtual host:出于多租户和安全因素设计的,把 AMQP 的基本组件划分到一个虚拟的分组中,类似于网络中的 namespace 概念。当多个不同的用户使用同一个 RabbitMQserver 提供的服务时,可以划分出多个vhost,每个用户在自己的 vhost 创建 exchange/queue 等
- Connection:publisher/consumer 和 broker 之间的 TCP 连接
- Channel:如果每一次访问 RabbitMQ 都建立一个 Connection,在消息量大的时候建立 TCP Connection的开销将是巨大的,效率也较低。Channel 是在 connection 内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的 channel 进行通讯,AMQP method 包含了channel id 帮助客户端和message broker 识别 channel,所以 channel 之间是完全隔离的。Channel 作为轻量级的 Connection 极大减少了操作系统建立 TCP connection 的开销
- Exchange:message 到达 broker 的第一站,根据分发规则,匹配查询表中的 routing key,分发消息到queue 中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) andfanout (multicast)
- Queue:消息最终被送到这里等待 consumer 取走
- Binding:exchange 和 queue 之间的虚拟连接,binding 中可以包含 routing key。Binding 信息被保存到 exchange 中的查询表中,用于 message 的分发依据
三、RabbitMQ五种消息发送模式
1,简单队列
(1)生产者将消息发送到队列,消费者从队列获取消息。
(2)一个队列对应一个消费者。
2,工作队列
(1)一个生产者,多个消费者。
(2)一个消息发送到队列时,只能被一个消费者获取。
(3)多个消费者并行处理消息,提升消息处理速度。
3,发布/订阅模式(Publish/Subcribe)
将消息发送到交换机,队列从交换机获取消息,队列需要绑定到交换机。
(1)一个生产者,多个消费者。
(2)每一个消费者都有自己的一个队列。
(3)生产者没有将消息直接发送到队列,而是发送到交换机。
(4)每一个队列都要绑定到交换机。
(5)生产者发送的消息,经过交换机到达队列,实现一个消息被多个消费者获取的目的。
(6)交换机类型为“fanout”。
注意:交换机本身没有存储消息的能力,消息只能存储到队列中。
4,路由模式(Routing)
(1)路由模式的交换机类型为“direct”。
(2)绑定队列到交换机时指定 key,即路由键,一个队列可以指定多个路由键。
(3)生产者发送消息时指定路由键,这时,消息只会发送到绑定的key的对应队列中。
5,主题模式(Topic)
(1) 绑定队列到交换机指定key时,进行通配符模式匹配。
(2) 符号“#”匹配一个或多个词,“*”匹配不多不少一个词。
四、RabbitMQ四种交换机
有4种不同的交换机类型:
- 扇形交换机:Fanout exchange
- 直连交换机:Direct exchange
- 主题交换机:Topic exchange
- 首部交换机:Headers exchange
1,扇形交换机
(1)扇形交换机是最基本的交换机类型,它所能做的事情非常简单———广播消息。
(2)扇形交换机会把能接收到的消息全部发送给绑定在自己身上的队列。
(3)因为广播不需要“思考”,所以扇形交换机处理消息的速度也是所有的交换机类型里面最快的。
2,直连交换机
(1)直连交换机是一种带路由功能的交换机,一个队列会和一个交换机绑定,除此之外再绑定一个routing_key
(2)当消息被发送的时候,需要指定一个binding_key,这个消息被送达交换机的时候,就会被这个交换机送到指定的队列里面去。
(3)同样的一个binding_key也是支持应用到多个队列中的,这样当一个交换机绑定多个队列,就会被送到对应的队列去处理。
3,主题交换机
(1)发送到主题交换机上的消息需要携带指定规则的routing_key
(2)主题交换机会根据这个规则将数据发送到对应的(多个)队列上。
(3)主题交换机的routing_key采用通配符的方式,其中:*表示一个单词;#表示任意数量(零个或多个)单词。
当一个队列的绑定键为#的时候,这个队列将会无视消息的路由键,接收所有的消息。
4,首部交换机
首部交换机和扇形交换机都不需要路由键routingKey,交换机时通过Headers头部来将消息映射到队列的,有点像HTTP的Headers,Hash结构中要求携带一个键“x-match”,这个键的Value可以是any或者all,这代表消息携带的Hash是需要全部匹配(all),还是仅匹配一个键(any)就可以了。相比直连交换机,首部交换机的优势是匹配的规则不被限定为字符串(string)而是Object类型。
- any: 只要在发布消息时携带的有一对键值对headers满足队列定义的多个参数arguments的其中一个就能匹配上,注意这里是键值对的完全匹配,只匹配到键了,值却不一样是不行的
- all:在发布消息时携带的所有Entry必须和绑定在队列上的所有Entry完全匹配
五、RabbitMQ集群架构模式
集群目的就是为了实现rabbitmq的高可用性,集群分为2种
- 普通集群:主备架构,只是实现主备方案,不至于主节点宕机导致整个服务无法使用
- 镜像集群:同步结构,基于普通集群实现的队列同步
1、普通集群:
slave节点复制master节点的所有数据和状态,除了队列数据,队列数据只存在master节点,但是Rabbitmq slave节点可以实现队列的转发,也就是说消息消费者可以连接到slave节点,但是slave需要连接到master节点转发队列,由此说明只能保证了服务可以用,无法达到高可用。slave节点队列可以查看到,但是不会同步数据
2、镜像集群:
基于普通集群实现队列的集群主从,消息会在集群中同步(至少三个节点)
3、镜像集群部署
环境准备:
配置hosts:
cat >> /etc/hosts << EOL
192.168.12.10 controller
192.168.12.11 standby1
192.168.12.12 standby2
EOL
配置.erlang.cookie:
RabbitMQ 的集群是依赖 erlang 集群,而 erlang 集群是通过这个 cookie 进行通信认证的,因此,三台机器的配置文件需要一致
- 目录:/var/lib/rabbitmq/.erlang.cookie (隐藏文件)
rabbitmq-server -detached
#启动rabbitmq服务才能查看到.erlang.cookie文件(三台都要启动)
rabbitmqctl stop_app
#停止掉2个standby节点,不然复制后操作会提示认证问题,因为erlang.cookie改变了,需要kill才行
scp /var/lib/rabbitmq/.erlang.cookie root@standby1:/var/lib/rabbitmq/
scp /var/lib/rabbitmq/.erlang.cookie root@standby2:/var/lib/rabbitmq/
#替换erlang.cookie文件
加入集群(节点操作加入):
rabbitmqctl cluster_status
#查看集群,默认集群就是自己
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@controller
rabbitmqctl start_app
#停止服务、重启之前的数据、加入集群
查看集群状态:
开启web管理页面:
rabbitmq-plugins enable rabbitmq_management (三个节点)
#url:http://192.168.12.10:15672/
#默认账号:guest guest
实现队列的集群:
基于普通镜像通过配置策略的方式实现,policy可以选择exchanges 或者 queue 的数据需要复制同步,以及如何复制同步
- 可以基于命令行配置
- 支持web管理界面配置
命令行配置策略格式:
rabbitmqctl set_policy [-p ] [–priority <priorityz] [–apply-to <apply-to2]
- -p Vhost: 可选参数,针对指定vhost下的queue进行设置
- Name:priority 名称
- Pattern: queue的匹配模式(使用正则表达式)
- Definition:镜像定义,包括三个部分ha-mode, ha-params, ha-sync-mode
ha-mode:指明镜像队列的模式,有效值为all/exactly/nodes
all:表示在集群中所有的节点上进行镜像
exactly:表示在指定个数的节点上进行镜像,节点的个数由ha-params指定
nodes:表示在指定的节点上进行镜像,节点名称通过ha-params指定
ha-params: ha-mode模式需要用到的参数
ha-sync-mode:进行队列中消息的同步方式,有效值为automatic和manual - priority:可选参数, policy的优先级
配置策略:
rabbitmqctl set_policy ha-all '^' '{"ha-mode":"all","ha-sync-mode":"automatic"}'
#策略名 ha-all
#匹配所有的队列,也可以具体单个,比如'^test'
#三个节点都进行队列镜像
#自动同步
查看策略:
rabbitmqctl list_policies
测试关闭controller节点:
rabbitmqctl stop_app
查看后发现节点已经变成standby2,数量也减少了一个
恢复controller节点:
rabbitmqctl start_app
查看后,说明集群节点不会被抢回,其实这样也是合理的
4、卸载rabbitmq(干净)
yum -y remove rabbitmq-server.noarch
yum -y remove erlang-*
rm -rf /usr/lib64/erlang
rm -rf /var/lib/rabbitmq