目录
一、规划
1、服务器
OS | 应用 | Hostname | 备注 |
---|---|---|---|
CentOS 7.4(192.168.139.162) | HA + Keepalived | ha_1 | 集群高可用(master) |
CentOS 7.4(192.168.139.160) | HA + Keepalived | ha_2 | 集群高可用(backup) |
CentOS 7.4(192.168.139.158) | Erlang 23.2.5、RabbitMQ 3.9.7 | mq_1 | mq_1 磁盘节点 |
CentOS 7.4(192.168.139.137) | Erlang 23.2.5、RabbitMQ 3.9.7 | mq_2 | mq_2 内存节点(加入mq_1集群) |
CentOS 7.4(192.168.139.138) | Erlang 23.2.5、RabbitMQ 3.9.7 | mq_3 | mq_3 内存节点(加入mq_1集群) |
2、资源下载
- Erlang 下载1:http://packages.erlang-solutions.com/erlang/rpm/centos/7/x86_64/
Erlang 下载2(GitHub):https://github.com/rabbitmq/erlang-rpm/releases/tag/v23.2.5 - RabbitMQ 下载:https://github.com/rabbitmq/rabbitmq-server/releases/tag/v3.9.7
注:
RabbitMQ 需对应指定的 Erlang 版本,否则部署过程中可能会报错。
RabbitMQ 指定的 Erlang 版本对照表:https://www.rabbitmq.com/which-erlang.html
3、整体架构
# 拓扑结构
=================================================================================
[vip: 192.168.139.110]
|
[LB1 ha_1] [LB2 ha_2]
192.168.139.162 192.168.139.160
| | |
[mq_1] [mq_2] [mq_3]
192.168.139.158 192.168.139.137 192.168.139.138
# 访问方式
=================================================================================
HA定义的端口号为:8888
http://192.168.139.110:8888/
二、部署
2.1 集群部署
2.1.1 安装 Erlang(三台都操作)
1、下载 Erlang RPM 包
wget https://github.com/rabbitmq/erlang-rpm/releases/download/v23.2.5/erlang-23.2.5-1.el7.x86_64.rpm
2、安装依赖
yum install -y *epel* gcc-c++ unixODBC unixODBC-devel openssl-devel ncurses-devel
3、安装 Erlang
yum install -y erlang-23.2.5-1.el7.x86_64.rpm
4、查看是否安装
[root@mq_1 ~]# erl
Erlang/OTP 23 [erts-11.1.8] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [hipe]
Eshell V11.1.8 (abort with ^G)
1>
# 到此,说明 Erlang 环境已经安装完成
2.1.2 安装 RabbitMQ
1、下载 RabbitMQ RPM 包(三台都操作)
wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.9.7/rabbitmq-server-3.9.7-1.el7.noarch.rpm
2、安装 RabbitMQ(三台都操作)
yum install -y rabbitmq-server-3.9.7-1.el7.noarch.rpm
3、启动 RabbitMQ(三台都操作)
systemctl start rabbitmq-server
systemctl enable rabbitmq-server
4、启动 RabbitMQ 内置 web 插件(三台都操作)
rabbitmq-plugins enable rabbitmq_management
5、重启 RabbitMQ(三台都操作)
systemctl restart rabbitmq-server
6、端口说明
2.1.3 开始部署集群
1、创建磁盘节点(三台都操作)
mkdir -p /data/rabbitmq/data # 存放数据的目录
mkdir -p /data/rabbitmq/logs # 存放日志的目录
chown rabbitmq.rabbitmq -R /data/ # 修改目录的权限
2、创建配置文件(三台都操作)
vim /etc/rabbitmq/rabbitmq-env.conf
RABBITMQ_MNESIA_BASE=/data/rabbitmq/data
RABBITMQ_LOG_BASE=/data/rabbitmq/logs
3、重启 RabbitMQ(三台都操作)
systemctl restart rabbitmq-serve
# 此时这三台机器都是磁盘节点
4、将 mq_1 的 .erlang.cookie 文件拷贝至 mq_2、mq_3(mq_1操作)
Rabbitmq的集群是依附于erlang的集群来工作的,所以必须先构建起erlang的集群景象。Erlang的集群中各节点是经由多个cookie来实现的,这个cookie存放在
/var/lib/rabbitmq/.erlang.cookie
中,文件是400的权限。所以必须保证各节点cookie一致,不然节点之间就无法通信。
官方在介绍集群的文档中提到过.erlang.cookie 一般会存在这两个地址:第一个是home/.erlang.cookie;第二个地方就是/var/lib/rabbitmq/.erlang.cookie。如果我们使用解压缩方式安装部署的rabbitmq,那么这个文件会在{home}目录下,也就是$home/.erlang.cookie。如果我们使用rpm等安装包方式进行安装的,那么这个文件会在
/var/lib/rabbitmq
目录下。
scp /var/lib/rabbitmq/.erlang.cookie root@mq_2:/var/lib/rabbitmq/
scp /var/lib/rabbitmq/.erlang.cookie root@mq_3:/var/lib/rabbitmq/
5、将 mq_2、mq_3 作为内存节点加入 mq_1 节点集群中(mq_2和mq_3操作)
-
停止mq_2节点
# 注意不是停止 RabbitMQ 服务 rabbitmqctl stop_app #将mq_2以内存节点添加到磁盘节点mq_1 rabbitmqctl join_cluster --ram rabbit@mq_1 #启动节点 rabbitmqctl start_app
-
停止mq_3节点
# 注意不是停止 RabbitMQ 服务 rabbitmqctl stop_app #将mq_3以内存节点添加到磁盘节点mq_1 rabbitmqctl join_cluster --ram rabbit@mq_1 #启动节点 rabbitmqctl start_app
默认 RabbitMQ 启动后三者都是磁盘节点,但在 RabbitMQ 集群模式下,mq_1 是磁盘节点,而 mq_2 和 mq_3 则是内存节点。如果要以磁盘节点加入集群,去掉 --ram 参数即可。
# 如:以磁盘节点类型加入mq_1集群 rabbitmqctl join_cluster --ram rabbit@mq_1
6、查看集群状态(在 mq_1 操作)
[root@mq_1 ~]# rabbitmqctl cluster_status
7、创建用户(仅 mq_1 操作)
-
添加用户和密码
[root@mq_1 ~]# rabbitmqctl add_user zhurs 111111 Adding user "zhurs" ... Done. Don't forget to grant the user permissions to some virtual hosts! See 'rabbitmqctl help set_permissions' to learn more. # 说明: # 用户名/密码:zhurs/111111 # 默认管理员用户/密码:guest/guest
-
设置为管理员
[root@mq_1 ~]# rabbitmqctl set_user_tags zhurs administrator Setting tags for user "zhurs" to [administrator] ...
-
添加用户权限
[root@mq_1 ~]# rabbitmqctl set_permissions -p / zhurs ".*" ".*" ".*" Setting permissions for user "zhurs" in vhost "/" ... # 此处设置权限时注意'.*'之间需要有空格 三个'.*'分别代表了conf权限,read权限与write权限 # 例如:当没有给soho设置这三个权限前是没有权限查询队列,在ui界面也看不见
-
查看用户列表
[root@mq_1 ~]# rabbitmqctl list_users Listing users ... user tags zhurs [administrator] guest [administrator]
8、登录 RabbitMQ Web 管理控制台
http://192.168.139.158:15672/
用户名:zhurs
密码:111111
9、在 Web 端创建消息队列
2.2 镜像部署
2.2.1 集群镜像设置
[root@mq_1 ~]# rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
Setting policy "ha-all" for pattern "^" to "{"ha-mode":"all"}" with priority "0" for vhost "/" ...
再次在 RabbitMQ Web 端查看一下
2.2.2 负载均衡(HA)+ Keepalived
1、安装 HAProxy(在 ha_1、ha_2 上操作)
yum -y install haproxy
2、修改 HAProxy 配置(在 ha_1 、ha_2 上操作)
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
vim /etc/haproxy/haproxy.cfg
global # 全局
log 127.0.0.1 local2 info # 日志(info级别)
pidfile /var/run/haproxy.pid # 进程id
maxconn 4000 # 最大连接数(优先级低)
user haproxy # 用户
group haproxy # 用户组
daemon # 以后台形式运行
nbproc 1 # 工作进程数量,结合OS的CPU数量来写
defaults
mode http # 工作模式:默认7层负载均衡(HTTP)
log global
retries 3 # 健康检查,3次连接失败就认为服务器不可用
option redispatch # 服务不可用后重定向到其他健康服务器。
maxconn 4000 # 最大连接数(优先级中)
contimeout 5000 # ha服务器与后端服务器连接超时时间,单位毫秒ms
clitimeout 50000 # 客户端访问haproxy的超时时间
srvtimeout 50000 # 后端服务响应结果的超时时间
listen rabbitmq
bind *:8888 # 绑定端口(访问HA时加上该端口---该端口可自定义,不要冲突即可)
mode tcp # 工作模式:4层负载均衡(TCP),此时不受defaults模块的mode影响
balance roundrobin # 负载均衡3台MQ
server rabbitmq_1 192.168.139.158:15672 check inter 2000s rise 2 fall 3
server rabbitmq_2 192.168.139.138:15672 check inter 2000s rise 2 fall 3
server rabbitmq_3 192.168.139.138:15672 check inter 2000s rise 2 fall 3
systemctl restart haproxy
3、访问 HA( ha_1 测试一下)
http://192.168.139.162:8888/
如上图,HA 配置一切正常,接下来配置 HA 的高可用;
4、安装 keepalived(在 ha_1、ha_2 上操作)
yum install -y keepalived
5、修改 keepalived 配置文件
-
ha_1 上操作
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived global_defs { router_id mq1 # back改为directory2(该名字可自定义) } vrrp_instance VI_1 { state MASTER # 定义主还是备 interface ens33 # VIP绑定接口 virtual_router_id 80 # 整个集群的调度器一致 priority 100 # back改为50 advert_int 1 # 检查间隔,默认为1s authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.139.110/24 } }
-
ha_2 上操作
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak vim /etc/keepalived/keepalived.conf
! Configuration File for keepalived global_defs { router_id mq2 } vrrp_instance VI_1 { state BACKUP # 设置为backup interface ens33 virtual_router_id 80 priority 50 # back改为50 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.139.110/24 } }
6、启动 KeepAlived(在 ha_1、ha_2 上操作)
systemctl start keepalived
systemctl enable keepalived
7、在 ha_1 上查看一下是否生成 VIP
[root@ha_1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 00:0c:29:f5:60:f3 brd ff:ff:ff:ff:ff:ff
inet 192.168.139.162/24 brd 192.168.139.255 scope global dynamic ens33
valid_lft 1525sec preferred_lft 1525sec
inet 192.168.139.110/24 scope global secondary ens33
valid_lft forever preferred_lft forever
inet6 fe80::6c57:e3eb:af28:1c37/64 scope link
valid_lft forever preferred_lft forever
# 已生成192.168.139.110
8、通过 VIP 访问 MQ
http://192.168.139.110:8888/
==至此,就已经实现了 RabbitMQ 集群 + HA + Keepalived 的高可用部署了。==接下来就是开发人员的工作了,我们只需要向开发人员提供
三、总结
1、Erlang
2、RabbitMQ
RabbitMQ 是一个开源的,基于 AMQP 协议的可复用的企业消息系统。RabbitMQ 为消息队列中间件的一种,其他 MQ 还有 Kafka、ActiveMQ、RocketMQ 等。其主要有以下作用:
-
冗余:提供了镜像队列,防止单节点故障,保证信息的有效性;
-
横向扩展:多台 MQ 可平滑加入集群;
-
解耦: 进程之间耦合程度过高,改动一个进程,引发必须修改另一个进程,因此通过 MQ 实现解耦;
-
异步通信: 降低接口响应时间,提高服务性能;
最常见的使用场景就是下单、减库存:
- 同步通信模式,接口响应时间 = 下单 + 库存;
- 异步通信模式,接口响应时间 = 下单,基本上是提高了一倍的性能。
-
削峰:消息队列中的常用场景,一般在秒杀或抢够活动中使用广泛。
一般会因为流量过大,应用系统配置承载不了这股瞬间流量,导致系统直接挂掉。为解决这个问题,我们会将那股巨大的流量拒在系统的上层,即将其转移至 MQ 而不直接涌入我们的接口。
消息中间件的两种模式:
-
P2P模式(消息队列系统)
P2P模式包含三个角色:消息队列(Queue)、发送者(Sender)、接收者(Receiver)。每个消息都被发送到一个特定的队列,接收者从队列中获取消息。队列保留着消息,直到它们被消费或超时。
-
Pub-Sub模式(发布-订阅消息系统)
Pub/Sub模式包含三个角色:主题(Topic)、发布者(Publisher)、订阅者(Subscriber)。多个发布者将消息发送到Topic,系统将这些消息传递给多个订阅者。