一、概念
1、消息中间件
消息中间件也可以称消息队列,是指用高效可靠的消息传递机制进行与平台无关的数据交流,并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息队列模型,可以在分布式环境下扩展进程的通信。
2、RabbitMQ概念
RabbitMQ是使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、安全。AMQP协议更多用在企业系统内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。
二、消息中间件的特性
-
冗余(存储)
-
扩展性
-
可恢复性
-
顺序保证
-
缓冲
-
异步通信
三、消息中间件的两种模式
1、P2P模式
P2P模式包含三个角色:消息队列(Queue)、发送者(Sender)、接收者(Receiver)。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到它们被消费或超时。
P2P的特点:
-
每个消息只有一个消费者(Consumer),即一旦被消费,消息就不再在消息队列中
-
发送者和接收者之间在时间上没有依赖性,也就是说当发送者发送了消息之后,不管接收者有没有正在运行它不会影响到消息被发送到队列
-
接收者在成功接收消息之后需向队列应答成功
-
如果希望发送的每个消息都会被成功处理的话,那么需要P2P模式
2、Pub/Sub模式
Pub/Sub模式包含三个角色:主题(Topic)、发布者(Publisher)、订阅者(Subscriber) 。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。
Pub/Sub的特点:
-
每个消息可以有多个消费者
-
发布者和订阅者之间有时间上的依赖性。针对某个主题(Topic)的订阅者,它必须创建一个订阅者之后,才能消费发布者的消息
-
为了消费消息,订阅者必须保持运行的状态
-
如果希望发送的消息可以不被做任何处理、或者只被一个消息者处理、或者可以被多个消费者处理的话,那么可以采用Pub/Sub模型
四、普通集群搭建
1、环境准备
#三台虚拟主机:
192.168.10.133 rabbitmq-1
192.168.10.134 rabbitmq-2
192.168.10.135 rabbitmq-3
注:三台虚拟机处于同一网络下,如果跨广域网,效果变差
2、以一台虚拟机为例,安装rabbitmq服务
①配置域名解析,三台设备都做
[root@rabbitmq-1 ~]# vim /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.10.133 rabbitmq-1
192.168.10.134 rabbitmq-2
192.168.10.135 rabbitmq-3
②环境安装、rabbitmq服务安装
#安装依赖环境
[root@rabbitmq-1 ~]# yum install -y epel-release gcc-c++ unixODBC unixODBC-devel openssl-devel ncurses-devel
#yum安装erlang
[root@rabbitmq-1 ~]# curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash
[root@rabbitmq-1 ~]# yum install erlang-21.3.8.21-1.el7.x86_64
#erl环境测试;
[root@rabbitmq-1 ~]# erl
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:10] [hipe] [kernel-poll:false]
Eshell V9.3 (abort with ^G)
1>
#安装rabbitmq
https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.7.10
[root@rabbitmq-1 ~]# yum install rabbitmq-server-3.7.10-1.el7.noarch.rpm
注:rabbitmq版本与 erlang版本相互要对应,具体相对应版本可在rabbitmq官网查看:https://www.rabbitmq.com/news.html
# erlang官网
https://packagecloud.io/rabbitmq/erlang
3、rabbitmq开启远程登录
[root@rabbitmq-1 ~]# cp /usr/share/doc/rabbitmq-server-3.7.10/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config
#打开{loopback_users, []}的注释,并删除后面的逗号
[root@rabbitmq-1 ~]# vim /etc/rabbitmq/rabbitmq.config
%% The default "guest" user is only permitted to access the server
%% via a loopback interface (e.g. localhost).
%% {loopback_users, [<<"guest">>]},
%%
%% Uncomment the following line if you want to allow access to the
%% guest user from anywhere on the network.
{loopback_users, []}
4、启动rabbitmq服务
[root@rabbitmq-1 ~]# systemctl daemon-reload
[root@rabbitmq-1 ~]# systemctl start rabbitmq-server
[root@rabbitmq-1 ~]# systemctl enable rabbitmq-server #加入自启动
#打开web访问
[root@rabbitmq-1 ~]# rabbitmq-plugins enable rabbitmq_management
5、查看端口状态
[root@rabbitmq-1 ~]# ss -lntp | grep beam
25672端口:rabbitmq服务内部通信调用端口
15672端口:web界面登录端口
5672端口:开发调用端口
4369 端口:erlang发现端口
6、rabbitmq用户创建
rabbitmq服务搭建好后,有一个默认的用户,账号:guest 密码:guest
#添加一个用户
#admin为账号,123456为密码
[root@rabbitmq-1 ~]# rabbitmqctl add_user admin 123456
#将admin设置为管理账号
[root@rabbitmq-1 ~]# rabbitmqctl set_user_tags admin administrator
#查看用户
[root@rabbitmq-1 ~]# rabbitmqctl list_users
#设置admin权限
[root@rabbitmq-1 ~]# rabbitmqctl set_permissions -p "/" newrain ".*" ".*" ".*"
#三个'.*'分别代表了conf权限,read权限与write权限
7、访问rabbitmq的web界面:http://192.168.10.133:15672
#用账号:guest登录,密码:guest
#其余两台以同样的方式部署
五、rabbitmq集群部署
1.首先创建好数据存放目录和日志存放目录:三台都做
#目录位置可自定义
[root@rabbitmq-1 ~]# mkdir -p /data/rabbitmq/data
[root@rabbitmq-1 ~]# mkdir -p /data/rabbitmq/logs
#授权或者改目录属性
#[root@rabbitmq-1 ~]# chmod 777 -R /data/rabbitmq
[root@rabbitmq-1 ~]# chown rabbitmq.rabbitmq /data/ -R
#创建配置文件:
[root@rabbitmq-1 ~]# vim /etc/rabbitmq/rabbitmq-env.conf
[root@rabbitmq-1 ~]# cat /etc/rabbitmq/rabbitmq-env.conf
#数据存放位置
RABBITMQ_MNESIA_BASE=/data/rabbitmq/data
#日志存放位置
RABBITMQ_LOG_BASE=/data/rabbitmq/logs
#重启服务
[root@rabbitmq-1 ~]# systemctl restart rabbitmq-server
2.拷⻉erlang.cookie
Rabbitmq的集群是依附于erlang的集群来⼯作的,所以必须先构建起erlang的集群景象。Erlang的集群中,各节点是经由过程⼀个magic cookie来实现的,这个cookie存放在/var/lib/rabbitmq/.erlang.cookie中,⽂件是400的权限。所以必须保证各节点cookie⼀致,不然节点之间就⽆法通信。
注:我们用rabbitmq-1这个机子为主,复制他的.erlang.cookie文件给rabbitmq-2、rabbitmq-3
#复制给rabbitmq-2
[root@rabbitmq-1 ~]# scp /var/lib/rabbitmq/.erlang.cookie 192.168.10.134:/var/lib/rabbitmq/
#复制给rabbitmq-3
[root@rabbitmq-1 ~]# scp /var/lib/rabbitmq/.erlang.cookie 192.168.10.135:/var/lib/rabbitmq/
#分别重启rabbitmq-2、rabbitmq-3
[root@rabbitmq-2 ~]# systemctl restart rabbitmq-server
[root@rabbitmq-3 ~]# systemctl restart rabbitmq-server
3.将rabbitmq-2、rabbitmq-3作为内存、磁盘节点加⼊rabbitmq-1节点集群中
#在rabbitmq-2、rabbitmq-3执⾏如下命令:
#停止节点
[root@rabbitmq-2 ~]# rabbitmqctl stop_app
[root@rabbitmq-2 ~]# rabbitmqctl reset #如果有数据需要重置,没有则不用
#添加到内存节点,如果要加入磁盘节点,去掉--ram参数就行
[root@rabbitmq-2 ~]# rabbitmqctl join_cluster --ram rabbit@rabbitmq-1
Clustering node 'rabbit@rabbitmq-2' with 'rabbit@rabbitmq-1' ...
#启动节点
[root@rabbitmq-2 ~]# rabbitmqctl start_app
Starting node 'rabbit@rabbitmq-2' ...
(1)默认rabbitmq启动后是磁盘节点,在这个cluster命令下,rabbitmq-2和rabbitmq-3是内存节点,
mq-1是磁盘节点。
(2)如果要使mq-2、mq-3都是磁盘节点,去掉--ram参数即可。
(3)如果想要更改节点类型,可以使⽤命令rabbitmqctl change_cluster_node_type
disc(ram),前提是必须停掉rabbit应⽤
4、在rabbitmq-1磁盘节点上面查看集群情况
[root@rabbitmq-1 ~]# rabbitmqctl cluster_status
5.登录rabbitmq web管理控制台 ,查看状态:
rabbithttp-1:http://192.168.10.133:15672
rabbithttp-2:http://192.168.10.134:15672
rabbithttp-3:http://192.168.10.135:15672
六、rabbitmq 集群镜像配置
上面已经完成RabbitMQ默认集群模式,但并不保证队列的高可用性,尽管交换机、绑定这些可以复制到集群里的任何一个节点,但是队列内容不会复制。但队列节点宕机直接导致该队列无法应用,只能等待重启,所以要想在队列节点宕机或故障也能正常应用,就要复制队列内容到集群里的每个节点,必须要创建镜像队列。
镜像队列是基于普通的集群模式的,然后再添加一些策略,所以你还是得先配置普通集群,然后才能设置镜像队列,我们就以上面的集群接着做。
1、在三台虚拟机上都执行以下命令
[root@rabbitmq-1 ~]# rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
注:"-p Vhost" :vhost名称, "^"匹配所有的队列, ha-all 策略名称为ha-all, '{"ha-mode":"all"}' 策略模式为 all 即复制到所有节点,包含新增节点。
2、登录web界面查看
七、rabbitmq负载均衡搭建,使用haproxy搭建
1、新开一台虚拟机,安装haproxy服务
[root@haproxy ~]# yum -y install haproxy
2、修改haproxy配置文件 /etc/haproxy/haproxy.cfg
[root@haproxy ~]# vim /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
nbproc 4
daemon
# turn on stats unix socket
stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
defaults
mode http
log global
retries 3
timeout connect 10s
timeout client 1m
timeout server 1m
timeout check 10s
maxconn 2048
#---------------------------------------------------------------------
##监控查看本地状态#####
listen admin_stats
bind *:80 #web平台端口
mode http
option httplog
option httpclose
log 127.0.0.1 local0 err
stats uri /haproxy
stats auth admin:123456
stats refresh 30s
####################################
###反代监控
frontend server
bind *:5670 #代理端口
log global
mode tcp
#option forwardfor
default_backend rabbitmq
maxconn 3
backend rabbitmq
mode tcp
log global
balance roundrobin
server rabbitmq-1 192.168.10.133:5672 check inter 2000s rise 2 fall 3
server rabbitmq-2 192.168.10.134:5672 check inter 2000s rise 2 fall 3
server rabbitmq-3 192.168.10.135:5672 check inter 2000s rise 2 fall 3
3、登录web查看代理:http://192.168.10.136/haproxy
八、常见问题
1、使用 rabbitmq-server -detached命令启动rabbitmq时,出现以下提示Warning: PID file not written; -detached was passed,此时使用rabbitmqctl status提示服务已启动,可知此问题不用解决。
2、由于更改hostname文件,在每次rabbitmqctl stop或者rabbitmqctl cluster_status等,只要是rabbitmq的命令就报错,提示大概如下:
Cluster status of node rabbit@web2 ...
Error: unable to connect to node rabbit@web2: nodedown
DIAGNOSTICS
===========
attempted to contact: [rabbit@web2]
rabbit@web2:
* connected to epmd (port 4369) on web2
* epmd reports node 'rabbit' running on port 25672
* TCP connection succeeded but Erlang distribution failed
* Hostname mismatch: node "rabbit@mq2" believes its host is different. Please ensure that hostnames resolve the same way locally and on "rabbit@mq2"
current node details:
- node name: 'rabbitmq-cli-11@web2'
- home dir: /root
- cookie hash: SGwxMdJ3PjEXG1asIEFpBg==
此时先ps aux | grep mq
,然后kill -9
该进程,然后再rabbitmq-server -detached
即可解决。(即先强杀,再重新启动);或者退一下终端重新连接。
3、使用rabbitmqctl stop
,rabbitmq-server -detached
重新启动后,原先添加的用户admin、虚拟主机coresystem等均丢失,还需要重新添加。
4、returned an error: shutdown: failed to start child: Logger.ErrorHandler
原因:erlang版本与RabbitMQ的版本不对应
解决:根据 RabbitMQ Erlang Version Requirements 这个网页检查版本 https://www.rabbitmq.com/which-erlang.html
九、常用命令
1、插件管理
#开启某个插件
rabbitmq-plugins enable xxx
#关闭某个插件
rabbitmq-plugins disable xxx
#注意:重启服务器后生效。
2、 virtual_host管理
#新建
virtual_host:rabbitmqctl add_vhost xxx
#撤销
virtual_host:rabbitmqctl delete_vhost xxx
3、用户管理
#新建用户
rabbitmqctl add_user xxxpwd
#删除用户
rabbitmqctl delete_user xxx
#查看用户
rabbitmqctl list_users
#改密码
rabbimqctl change_password {username} {newpassword}
#设置用户角色
rabbitmqctlset_user_tags {username} {tag ...}
#Tag可以为 administrator,monitoring, management
4、其他使用命令
rabbitmq使用命令:
rabbitmq-plugins list ----查看安装的插件
rabbitmq-server -detached -----------启动RabbitMQ节点
rabbitmqctl start_app ----------启动RabbitMQ应用,而不是节点
rabbitmqctl stop_app ------停止
rabbitmqctl status ------查看状态
rabbitmqctl add_user mq 123456 -------设置用户和密码
rabbitmqctl set_user_tags mq administrator ------------------新增账户并设置为管理员
rabbitmq-plugins enable rabbitmq_management --------------------启用RabbitMQ_Management
rabbitmqctl cluster_status -------------------集群状态
rabbitmqctl forget_cluster_node rabbit@rabbit3 -------------------节点摘除
rabbitmqctl reset application----------------------重置
rabbitmqctl set_permissions -p "/" 123456 ".*" ".*" ".*" --------------授权
---------------------
#查看Connection,Queue,Channel,User
rabbitmqctl list_connections #列出所有连接
rabbitmqctl list_queues #列出所有队列
rabbitmqctl list_channels #列出所有通道
rabbitmqctl list_users #列出所有用户
#设置节点类型
#如果你想更换节点类型可以通过命令修改,如下:
rabbitmqctl stop_app
rabbitmqctl change_cluster_node_type dist
rabbitmqctl change_cluster_node_type ram
rabbitmqctl start_app
===================================================
#移除节点
#如果想要把节点从集群中移除,可使用如下命令实现:
rabbitmqctl stop_app
rabbitmqctl restart
rabbitmqctl start_app
=============================================
#集群重启顺序
#集群重启的顺序是固定的,并且是相反的。如下所述:
#启动顺序:磁盘节点 => 内存节点
#关闭顺序:内存节点 => 磁盘节点
#最后关闭必须是磁盘节点,不然可能回造成集群启动失败、数据丢失等异常情况。