Rabbitmq 介绍
RabbitMQ是世界最火的开源消息代理服务器,在全世界拥有超过35000个项目部署在Rabbitmq。
RabbitMQ 支持几乎所有的操作系统与编程语言。
Rabbit提供了高并发、高可用的成熟方案,支持多种消息协议,易于部署于使用。
rabbitmq 应用场景
1、异构系统的数据传递
2、高并发程序的流量控制
3、基于P2P,P2PPP的程序
4、分布式系统的事务一致性TCC
5、高可靠性的交易系统
一句话总结就是,两个以上系统进行数据交互传递的场景,用MQ来做数据解偶。
基本概念
AMQP,即Advanced Message Queuing Protocol,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间价不同产品,不同的开发语言等条件的限制。
AMQP是业界的标准,所有的MQ在实现信息间传递的时候,底层使用的协议就是AMQP协议。
Producer:生产者,消息的提供者
Consumer:消费者,消息的使用者
Message:消息,程序间的通信的数据
Queue:队列,消息存放的容器,消息先进先出
Vhost:虚拟主机,相当于MQ的“数据库”,用于存储队列
消息状态
Ready:消息已被送入队列,等待被消费
Unacked:
- 消息已经被消费者认领,但还未被确认“已被消费”
- Unacked状态下,消费者断开连接则消息回到“Ready”
- 没有确认,客户有没有断开连接,则一直处于Unacked
Finished:调用basicAck()方法后,表示消息已被消费,从队列中移除
Rabbitmq的常用模式
work Queue工作队列
在多个消息的情况下,work queue会将消息分配给不同的消费者,每个消费者都会接收到不同的消息,并且可以根据处理消息的速度来接收消息的数量,进而让消费者程序发挥最大性能。
Work Queue特别适合在集群环境中做异步处理,能最大程度发挥每一台服务器的性能。
发布(publish)/订阅(Subscribe)模式
发布/订阅模式中,生产者不在直接与队列绑定,而是将数据发送至“交换机Exchange”
交换机Exchange用于将数据按某种规则送入与之绑定的队列,进而供消费者使用
发布/订阅模式中,交换机将无差别的将所有消息送入与之绑定的队列,所有消费者拿到的消息完全相同,交换机的类型被称为fanout
路由Routing模式
路由模式是在发布订阅模式基础上的变种
发布订阅模式是无条件将所有消息分发给所有消费者队列
路由模式则是交换机根据routing key有条件的将数据筛选后发送给消费者队列
路由模式下交换机的类型被称为direct
主题Topic模式
主题topic模式是在Routing模式基础上,提供了对Routekey模糊匹配的功能,可以简化程序的编写。
主题模式下,模糊匹配表达式规则为
- * 匹配单个关键字
- # 匹配所有关键字
主题模式下交换机的类型被称为topic
RabbitMQ 消息确认机制
Rabbitmq 在传递消息的过程中充当了代理人(broker)的角色,那生产者(producer)怎样知道消息被正确投递到broker了呢?
RabbitMQ 提供了监听器(Listener)来接收消息投递的状态。
消息确认设计两种状态:confirm与return
confirm & return
confirm 代表生产者奖消息送到broker时发生的状态,后续会出现两种情况:
- ack表示broker已经奖数据接收
- nack 表示broker拒收消息。原因有多种,队列已满,限流,IO异常……
return代表消息被broker正常接收(ack)后,但broker没有对相应的队列进行投递时产生的状态,消息被退回给生产者。
注意:上面两种状态只代表生产者与broker之间消息投递的情况。与消费者是否接收/确认消息无关。
rabbitmq 安装
环境介绍
软件环境: rabbitmq 3.7.7
架构环境:三台centos 7.2 服务器
节点名 IP地址
c7-node1 192.168.28.71
c7-node2 192.168.28.72
c7-node3 192.168.28.73
安装步骤
注:因为rabbitmq 是使用erlang编写,所以还需要安装erlang环境
(1)下载相关程序
erlang 下载地址:https://packages.erlang-solutions.com/rpm/centos/7/x86_64/?C=N;O=D
rabbitmq下载地址:http://www.rabbitmq.com/download.html
(2)安装相关程序包
yum -y install esl-erlang_21.0-1~centos~7_amd64.rpm rabbitmq-server-3.7.7-1.el7.noarch.rpm
(3)启动控制台
rabbitmq-plugins enable rabbitmq_management
(4)设置cookie文件权限
chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie
(5)配置guest用户可以远程登录(rabbitmq 3.3以后禁止了)
# vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.7/ebin/rabbit.app {loopback_users, [<<"guest">>]}, 修改为 {loopback_users, []},
(6)启动服务
systemctl start rabbitmq-server
(7)访问web控制台,验证服务是否正常运行,访问地址http://ip:15672,用户名和密码都是guest
rabbitmq 的常用命令
启动与关闭
rabbitmq-server 前台启动服务
rabbitmq-server –detached 后台启动服务
rabbitmqctl stop 停止服务
终止与启动应用
rabbitmqctl start_app 启动应用
rabbitmqctl stop_app 终止应用
用户管理
rabbitmqctl add_user {username} {password} 创建新用户
rabbitmqctl delete_user {username} 删除用户
rabbitmqctl change_password {username}{newpassword} 重置密码
rabbitmqctl set_user_tags {username} {tag} 授予用户角色Tag
rabbitmqctl set_permissions –p / user_admin ‘.*’‘.*’‘.*’设置用户允许访问的vhost
RabbitMQ用户四种Tag
超级管理员(administrator):可登录管理控制台,可查看所有的信息,并且可以对用户,策略(policy)进行操作。
监控者(monitoring):登录管理控制台,同时可以查看rabbitmq节点的相关信息(进程数,内存使用情况,磁盘使用情况等)。
策略制定者(policymaker):可登录管理控制台,同时可以对policy进行管理。但无法查看节点的相关信息。
普通管理者(management):仅可登录管理控制台,无法看到节点信息,也无法对策略进行管理
rabbitmq 集群模式
主备模式(warren):实现rabbitmq的高可用集群,一般在并发和数据量不高的情况下,这种模型非常好用且简单。
镜像模式(mirror):集群模式非常经典的就是mirror镜像模式,保障100%数据不丢失,在实际工作中也是用的最多的。并且实现集群非常的简单,一般互联网大厂都会构建这种镜像集群模式。
远程模式(shovel):远程模式可以实现双活的一种模式,简称shovel模式,所谓shovel就是我们可以把消息进行不同数据中心的复制工作,我们可以跨地域让两个mq集群互联。
多活模式(federation):这种模式也是实现异地数据复制的主流模式,因为shovel模式配置比较复杂,所以一般来说实现异地集群都是使用这种双活或者多活模型来去实现的。这种模型需要依赖rabbitmq的federation插件,可以实现持续的可靠的AMQP数据通信,多活模式在实际配置与应用中非常的简单。
本文主要介绍rabbitmq 镜像集群
Rabbitmq 集群搭建
Rabbitmq 数据分为两类
(1)队列中的消息
(2)元数据信息
1、队列元数据:队列的名称及属性
2、交换器:交换器的名称及属性
3、绑定关系元数据:交换器与队列活着交换器与交换器之间的绑定关系
4、vhost元数据:为vhosts内的队列、交换器和绑定提供命名空间及安全属性
rabbitmq 集群主要解决的问题是元数据信息的高可用,和通过增加节点能线性的增加性能(CPU、内存)和容量(内存、磁盘),因为机器能够容纳的消息数量和节点数成正比 ——具有水平伸缩性
当集群中的一个节点崩溃时,该节点上的所有队列消息也有丢失,可以通过特殊的配置比如镜像队列来解决这个问题,客户端能够重新连接到集群中的任何其他节点并继续生产或者消费。
集群搭建过程
(1)修改hosts文件,在其上添加IP地址与节点名称的映射信息
(2)确保集群各个节点使用的cookie文件使用的是同一个值,可以获取node1节点的cookie值,然后将其复制到node2和node3节点上
# scp /var/lib/rabbitmq/.erlang.cookie node2:/var/lib/rabbitmq/ # scp /var/lib/rabbitmq/.erlang.cookie node3:/var/lib/rabbitmq/
(3)通过rabbitmqctl工具配置集群。
首先启动node1,node2,node3这三个节点的rabbitmq服务
rabbitmq-server –detached
接下来将三个节点组成一个集群,分别在node2和node3节点执行如下命令
rabbitmqctl stop_app rabbitmqctl reset rabbitmqctl join_cluster rabbit@c7-node1 rabbitmqctl start_app
查询集群节点状态,可以看到三个节点都已经加入到集群了
[root@c7-node1 ~]# rabbitmqctl cluster_status Cluster status of node rabbit@c7-node1 ... [{nodes,[{disc,['rabbit@c7-node1','rabbit@c7-node2','rabbit@c7-node3']}]}, {running_nodes,['rabbit@c7-node3','rabbit@c7-node2','rabbit@c7-node1']}, {cluster_name,<<"rabbit@c7-node1">>}, {partitions,[]}, {alarms,[{'rabbit@c7-node3',[]}, {'rabbit@c7-node2',[]}, {'rabbit@c7-node1',[]}]}]
注意:
1、如果关闭了集群中的所有节点,则需要确保在启动的时候最后关闭的那个节点是第一个启动的。如果第一个启动的不是最后关闭的节点,那么这个节点会等待最后关闭的节点启动。这个等待时间是30秒,如果没有等到,那么这个先启动的节点也会失败。
2、如果最后一个关闭的节点最终由于某些异常而无法启动,则可以通过rabbitmqctl forget_cluster_node 命令来将此节点剔出当前集群。如果集群中的所有节点由于某些非正常因素,比如断电而关闭,那么集群中的节点都会认为还有其他节点在它后面关闭,此时需要调用rabbitmqctl force_boot命令来启动一个节点,之后集群才能正常启动。
集群节点类型
rabbitmq中的每一个节点,不管是单一节点系统或者是集群中的一部分,要么是内存节点,要么是磁盘节点。
内存节点将所有的队列、交换器、绑定关系、用户、权限和vhosts的元数据定义都存储在内存中,而磁盘节点则将这些信息存储到磁盘中。
单节点的集群中必然只有磁盘类型的节点,否则当重启rabbitmq之后,所有关于系统的配置信息都会丢失。不过在集群中,可以选择配置部分节点为内存节点,这样可以获得更高的性能。
在集群中创建队列、交换器或者绑定关系的时候,这些操作直到所有集群节点都成功提交元数据变更后才会返回。对内存节点来说,这意味着将变更写入内存;而对于磁盘节点来说,这意味着昂贵的磁盘写入操作。内存节点可以提供出色的性能,磁盘节点能够保证集群配置的信息和可靠性,如何在这两者之间进行抉择呢?
Rabbitmq只要求在集群中至少有一个磁盘节点,所有其他节点可以是内存节点。当节点加入或者离开集群时,他们必须将变更通知到至少一个磁盘节点。如果只有一个磁盘节点,而且不凑巧的是它刚好崩溃了,那么集群可以继续发送或者接收消息,但是不能创建队列、交换器、绑定关系、用户、以及更改权限、添加或删除集群节点的操作了。也就是说,如果集群中唯一的磁盘节点崩溃,集群仍然可以保持运行,但是直到该节点恢复到集群前,你无法更改任何东西。所以在建立集群的时候应该保证有两个或者多个磁盘节点的存在。
在内存节点重启后,它们会连接到预先配置的磁盘节点,下载当前集群元数据副本。当在集群中添加内存节点时,确保告知其所有的磁盘节点(内存节点唯一存储到磁盘的元数据信息是集群中磁盘节点的地址)。只要内存节点可以找到至少一个磁盘节点,那么他就能在重启后重新加入集群中。
除非使用的是rabbitmq的RPC功能,否则创建队列、交换器及绑定关系的操作确是甚少,大多数的操作就是生产或者消费消息。为了确保集群消息的可靠性,或者在不确定使用磁盘节点或者内存节点的时候,建议全部使用磁盘节点。
指定加入集群的节点为内存节点(默认不添加–ram则表示此节点为磁盘节点)
rabbitmqctl join_cluster rabbit@c7-node1 --ram
如果集群已经创建好了,那么也可以使用rabbitmqctl change_cluster_node_type {disc,ram}命令来切换节点的类型,其中disc表示磁盘节点,而ram表示内存节点,切换方式如下所示
[root@c7-node2 ~]# rabbitmqctl stop_app [root@c7-node2 ~]# rabbitmqctl change_cluster_node_type ram [root@c7-node2 ~]# rabbitmqctl start_app [root@c7-node2 ~]# rabbitmqctl cluster_status Cluster status of node rabbit@c7-node2 ... [{nodes,[{disc,['rabbit@c7-node3','rabbit@c7-node1']}, {ram,['rabbit@c7-node2']}]}, {running_nodes,['rabbit@c7-node1','rabbit@c7-node3','rabbit@c7-node2']}, {cluster_name,<<"rabbit@c7-node1">>}, {partitions,[]}, {alarms,[{'rabbit@c7-node1',[]}, {'rabbit@c7-node3',[]}, {'rabbit@c7-node2',[]}]}]
镜像集群(HA方案)
镜像模式:把需要的队列做成镜像队列,消息存在于多个节点,属于RabbitMQ的HA方案。
优点:镜像队列集群与普通集群不同之处在于,queue中的消息数据会在镜像节点中同步,消息写入队列,都交给master节点进行写入,然后同步至各slave。当master当机后,内部会从slave节点重新选举出一个新的master节点,从而有效的防止消息丢失及服务不可用等问题。
缺点:正所谓凡事有利亦有弊,正是因为涉及到主节点之间消息的同步,当内部需要同步的镜像队列较多,数据量很大的时候,磁盘IO,网络带宽等都会成为master节点的瓶颈,进而影响整个集群的性能。并且由于各节点之间消息的同步(即各镜像队列数据完全一致),也丧失了通过新增节点线性增加性能(cpu、内存)和容量(内存、磁盘)的能力。
配置方式
镜像队列主要是通过添加相应的policy来完成的,配置参数如下:
策略名称为ha-allqueue,策略模式为 all 即复制到所有节点,包含新增节点,策略正则表达式为 “^” 表示所有匹配所有队列名称。
rabbitmqctl set_policy -p / ha-allqueue "^" '{"ha-mode":"all"}'
验证配置是否成功,打开web页面查看,node节点出现+2就表示有两个镜像节点,查看queues信息,也会出现两个mirrors节点信息,说明镜像队列配置成功
转载请注明:西门飞冰的博客 » rabbitmq 介绍及集群搭建