消息队列的目的是为了实现各个 APP 之间的通讯,APP 基于 MQ 实现消息的发送和接收实现应用程序之间的通讯,这样多个应用程序可以运行在不同的主机上,通过 MQ 就可以实现跨网络通信,因此 MQ 实现了业务的解耦和异步机制。
帮助业务系统结构提升开发效率和系统稳定性,消息队列主要具有以下特点:
RabbitMQ是一款使用Erlang语言开发的,实现AMQP(高级消息队列协议)的开源消息中间件。首先要知道一些RabbitMQ的特点,官网可查:
环境:centos7.9
下载地址:https://www.rabbitmq.com/download.html
RabbitMQ是采用 Erlang语言开发的,所以系统环境必须提供 Erlang环境,需要是安装 Erlang
这里安装最新版本3.8.14的RabbitMQ,对应的Erlang版本推荐23.x,我们下载erlang-23.2.7-2.el7.x86_64.rpm
[root@localhost ~]# wget https://packagecloud.io/rabbitmq/erlang/packages/el/7/erlang-23.2.7-2.el7.x86_64.rpm
root@localhost(192.168.1.52)~>rpm -ivh erlang-23.2.7-2.el7.x86_64.rpm
warning: erlang-23.2.7-2.el7.x86_64.rpm: Header V4 RSA/SHA1 Signature, key ID 6026dfca: NOKEY
Preparing... ################################# [100%]
Updating / installing...
1:erlang-23.2.7-2.el7 ################################# [100%]
root@localhost(192.168.1.52)~>
查看版本
root@localhost(192.168.1.52)~>erl -v
Erlang/OTP 23 [erts-11.1.8] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]
Eshell V11.1.8 (abort with ^G)
1>
解决依赖
在RabiitMQ安装过程中需要依赖socat插件,首先安装该插件
root@localhost(192.168.1.52)~>yum install -y socat
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
解压rabbitmq安装包
root@localhost(192.168.1.52)~>rpm -Uvh rabbitmq-server-3.12.4-1.el8.noarch.rpm
warning: rabbitmq-server-3.12.4-1.el8.noarch.rpm: Header V4 RSA/SHA512 Signature, key ID 6026dfca: NOKEY
error: Failed dependencies:
erlang >= 25.0 is needed by rabbitmq-server-3.12.4-1.el8.noarch
root@localhost(192.168.1.52)~>
报错 因为rabbit-3-12要求erlang版本大于25
但是我上面的版本是23 所以我才去降低rabbitmq的版本
root@localhost(192.168.1.52)~>rpm -ivh rabbitmq-server-3.8.14-1.el7.noarch.rpm
warning: rabbitmq-server-3.8.14-1.el7.noarch.rpm: Header V4 RSA/SHA256 Signature, key ID 6026dfca: NOKE
Preparing... ################################# [100%]
package rabbitmq-server-3.8.14-1.el7.noarch is already installed
# 启动rabbitmq
systemctl start rabbitmq-server
# 查看rabbitmq状态
systemctl status rabbitmq-server
默认情况下,rabbitmq没有安装web端的客户端软件,需要安装才可以生效
# 打开RabbitMQWeb管理界面插件
rabbitmq-plugins enable rabbitmq_management
root@localhost(192.168.1.52)~>rabbitmq-plugins enable rabbitmq_management
Enabling plugins on node rabbit@localhost:
rabbitmq_management
The following plugins have been configured:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
Applying plugin configuration to rabbit@localhost...
The following plugins have been enabled:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
started 3 plugins.
root@localhost(192.168.1.52)~>
rabbitmq有一个默认的账号密码guest,但该情况仅限于本机localhost进行访问,所以需要添加一个远程登录的用户
# 添加用户
rabbitmqctl add_user 用户名 密码
# 设置用户角色,分配操作权限
rabbitmqctl set_user_tags 用户名 角色
# 为用户添加资源权限(授予访问虚拟机根节点的所有权限)
rabbitmqctl set_permissions -p / 用户名 ".*" ".*" ".*"
这里创建用户zfl,密码123456,设置administrator角色,赋予所有权限
root@localhost(192.168.1.52)~>rabbitmqctl add_user zfl 123456
Adding user "zfl" ...
Done. Don't forget to grant the user permissions to some virtual hosts! See 'rabbitmqctl help set_permissions' to learn more.
root@localhost(192.168.1.52)~>rabbitmqctl set_user_tags zfl administrator
Setting tags for user "zfl" to [administrator] ...
root@localhost(192.168.1.52)~>rabbitmqctl set_permissions -p / zfl ".*" ".*" ".*"
Setting permissions for user "zfl" in vhost "/" ...
root@localhost(192.168.1.52)~>
旧版本允许登录方式:
# vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.8.3/ebin/rabbit.app
39 {loopback_users, []}, #删除被禁止登陆的 guest 账户
# systemctl restart rabbitmq-server.service #重启 rabbitmq 服务
新版本的guset远程登录方式
开启guest用户远程登录功能
ls /etc/rabbitmq
enabled_plugins
#创建配置文件开启远程登录功能
echo " loopback_users = none"> /etc/rabbitmq/rabbitmq.conf
systemcti restart rabbitmg-server.service
# 修改密码
rabbitmqctl change_ password 用户名 新密码
# 删除用户
rabbitmqctl delete_user 用户名
# 查看用户清单
rabbitmqctl list_users
docker run -itd --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.12-management
docker run -itd --name rabbitmq -e RABBITMQ_DEFAULT_USER=zfl -e RABBITMQ_DEFAULT_PASS=123456 -p 5672:5672 -p 15672:15672 rabbitmq:3.12-management
创建 vhost
root@localhost(192.168.1.52)~>rabbitmqctl add_vhost zoey
Adding vhost "zoey" ...
root@localhost(192.168.1.52)~>
列出所有 vhost
root@localhost(192.168.1.52)~> rabbitmqctl list_vhosts
Listing vhosts ...
name
/
zoey
root@localhost(192.168.1.52)~>
# 添加用户
rabbitmqctl add_user 用户名 密码
# 设置用户角色,分配操作权限
rabbitmqctl set_user_tags 用户名 角色
# 为用户添加资源权限(授予访问虚拟机根节点的所有权限)
rabbitmqctl set_permissions -p / 用户名 ".*" ".*" ".*"
普 通 集 群 模 式:queue 创建之后,如果没有其它 policy,消息实体只存在于其中
一个节点,A、B 两个 Rabbitmq 节点仅有相同的元数据,即队列结构,但队列的
数据仅保存有一份,即创建该队列的 rabbitmq 节点(A 节点),当消息进入 A 节
点的 Queue 中后,consumer 从 B 节点拉取时,RabbitMQ 会临时在 A、B 间进行
消息传输,把 A 中的消息实体取出并经过 B 发送给 consumer,所以 consumer
可以连接每一个节点,从中取消息,该模式存在一个问题就是当 A 节点故障后,
B 节点无法取到 A 节点中还未消费的消息实体。
把需要的队列做成镜像队列,存在于多个节点,属于 RabbitMQ 的 HA 方案(镜
像模式是在普通模式的基础上,增加一些镜像策略)
该模式解决了普通模式中的数据丢失问题,其实质和普通模式不同之处在于,消
息实体会主动在镜像节点间同步,而不是在 consumer 取数据时临时拉取,该模
式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之
大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉,所以在
对可靠性要求较高的场合中适用,一个队列想做成镜像队列,需要先设置 policy,
然后客户端创建队列的时候,rabbitmq 集群根据“队列名称”自动设置是普通集
群模式或镜像队列。
内存节点:只将数据保存到内存
磁盘节点:保存数据到内存和磁盘。
内存节点虽然不写入磁盘,但是它执行比磁盘节点要好,集群中,只需要一个磁
盘节点来保存数据就足够了如果集群中只有内存节点,那么不能全部停止它们,
否则所有数据消息在服务器全部停机之后都会丢失。
在一个 rabbitmq 集群里,有 3 台或以上机器,其中 1 台使用磁盘模式,其它节
点使用内存模式,内存节点无访问速度更快,由于磁盘 IO 相对较慢,因此可作
为数据备份使用。
192.168.199.50
192.168.199.51
192.168.199.52
hostnamectl set-hostname mq-server1
[root@master ~]# cat >> /etc/hosts <
写好一个脚本 直接执行
[root@mq-server1 rabbit]# cat rabbitmqinstall.sh
#! /bin/bash
rpm -ivh erlang-23.2.7-2.el7.x86_64.rpm
if [ $? -eq 0 ];then
echo erlang安装成功;
else
break
fi
yum install -y socat
if [ $? -eq 0 ];then
echo socat安装成功;
else
break
fi
rpm -ivh rabbitmq-server-3.8.14-1.el7.noarch.rpm
if [ $? -eq 0 ];then
echo rabbitmq安装成功;
else
break
fi
systemctl start rabbitmq-server
if [ $? -eq 0 ];then
echo rabbitmq启动成功;
else
echo rabbitmq启动失败
fi
#配置web端
rabbitmq-plugins enable rabbitmq_management
#修改guest用户可以直接登录
echo " loopback_users = none"> /etc/rabbitmq/rabbitmq.conf
systemctl restart rabbitmq-server
Rabbitmq 的集群是依赖于 erlang 的集群来工作的,所以必须先构建起 erlang 的集群环境,而 Erlang 的集群中各节点是通过一个 magic cookie 来实现的,这个cookie 存放在/var/lib/rabbitmq/.erlang.cookie 中,文件是 400 的权限,所以必须保证各节点 cookie 保持一致,否则节点之间就无法通信。
各服务器关闭RabbitMQ:
[root@mq-server1 rabbit]# systemctl stop rabbitmq-server
在192.168.199.50上
[root@mq-server1 rabbit]scp -r /var/lib/rabbitmq/.erlang.cookie 192.168.199.51:/var/lib/rabbitmq/.erlang.cookie
[root@mq-server1 rabbit]# scp -r /var/lib/rabbitmq/.erlang.cookie 192.168.199.52:/var/lib/rabbitmq/.erlang.cookie
在启动服务rabbitmq
[root@mq-server1 rabbit]# systemctl start rabbitmq-server
[root@mq-server1 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@mq-server1 ...
Basics
Cluster name: rabbit@mq-server1
Disk Nodes
rabbit@mq-server1
Running Nodes
rabbit@mq-server1
Versions
rabbit@mq-server1: RabbitMQ 3.8.14 on Erlang 23.2.7
Maintenance status
Node: rabbit@mq-server1, status: not under maintenance
Alarms
(none)
Network Partitions
(none)
Listeners
Node: rabbit@mq-server1, interface: [::], port: 15672, protocol: http, purpose: HTTP API
Node: rabbit@mq-server1, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@mq-server1, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Feature flags
Flag: drop_unroutable_metric, state: enabled
Flag: empty_basic_get_metric, state: enabled
Flag: implicit_default_bindings, state: enabled
Flag: maintenance_mode_status, state: enabled
Flag: quorum_queue, state: enabled
Flag: user_limits, state: enabled
Flag: virtual_host_metadata, state: enabled
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbitmqserver1 --ram
mq-server1默认为disk节点
只需要将mq-server2 mq-server3设置为内存节点
在mq-server2上面将 加入到mq-server1上并作为内存节点
并设置将rabbitmqserver2 为磁盘存储
rabbitmqctl stop_app
rabbitmqctl reset reset #清空元数据
rabbitmqctl join_cluster rabbit@mq-server1 mq-server1
并成为内存节点,不加--ram 默认是磁盘
[root@mq-server2 ~]# rabbitmqctl stop_app
[root@mq-server2 ~]# rabbitmqctl reset
Resetting node rabbit@mq-server2 ...
[root@mq-server2 ~]# rabbitmqctl join_cluster rabbit@mq-server1 --ram
Clustering node rabbit@mq-server2 with rabbit@mq-server1
[root@mq-server2 ~]#
mq-server3上面将 加入到mq-server1上
[root@mq-server3 ~]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@mq-server3 ...
[root@mq-server3 ~]# rabbitmqctl reset
Resetting node rabbit@mq-server3 ...
[root@mq-server3 ~]# rabbitmqctl join_cluster rabbit@mq-server1 --ram
Clustering node rabbit@mq-server3 with rabbit@mq-server1
[root@mq-server3 ~]#
[root@mq-server1 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@mq-server1 ...
Basics
Cluster name: rabbit@mq-server1
Disk Nodes
rabbit@mq-server1
RAM Nodes
rabbit@mq-server2
rabbit@mq-server3
Running Nodes
rabbit@mq-server1
rabbit@mq-server2
rabbit@mq-server3
Versions
rabbit@mq-server1: RabbitMQ 3.8.14 on Erlang 23.2.7
rabbit@mq-server2: RabbitMQ 3.8.14 on Erlang 23.2.7
rabbit@mq-server3: RabbitMQ 3.8.14 on Erlang 23.2.7