Linux安装RabbitMq和Erlang-搭建集群
Linux安装RabbitMq和Erlang-搭建集群
Rabbitmq rpm包 下载地址:https://github.com/rabbitmq/rabbitmq-server/releases
Erlang rpm包 下载地址:https://github.com/rabbitmq/erlang-rpm/releases
Rabbitmq Erlang版本要求:https://www.rabbitmq.com/which-erlang.html
Linux中安装RabbitMq
下载好的 rpm包,放入 /usr/local/software/下:
rpm常用命令
-
-i 安装软件包(–install)
-
–nodeps 不验证软件包的依赖
-
–force 强制安装,即使覆盖其他包的文件也要安装
-
-v 可视化,提供更多的详细信息的输出
-
-h 显示安装进度
-
-a 查询所有已经安装的软件包
-
-f 查询文件所属于的软件包
-
-q 查询软件包(通常用来看下还未安装的软件包,注意,查询时不需要带包名后缀)
-
-l 显示软件包的文件列表
-
-e 卸载指定软件包(注意,卸载时需要指定具体包名后缀)
-
-U 升级软件包,很少用
常用组合:
-
-ivh 安装指定rmp包并显示安装进度
-
-qa 查询所有已经安装的软件包
-
-qi 查询软件包安装信息
-
-ql 显示软件包的文件列表
-
-qf 查询文件所属的文件包
安装文件
-
安装erlang:
rpm -ivh erlang-23.0-1.el7.x86_64.rpm
-
安装rabbitmq所依赖的插件:
yum install socat -y
-
安装rabbitmq:
rpm -ivh rabbitmq-server-3.8.8-1.el7.noarch.rpm
el*
:表示发行商的版本,el6表示这个软件包是在rhel6.x/centos6.x下使用;rpm包有个特点,centOS7的rpm包一般只能装到CentOS7的系统里,CentOS6的软件包只能装到CentOS6的系统里
noarch
:说明这样的软件包可以在任何平台安装和运行,不需要特定的硬件平台
常用命令
-
添加开机启动服务:
chkconfig rabbitmq-server on
-
启动服务:
/sbin/service rabbitmq-server start
-
查看服务状态:
/sbin/service rabbitmq-server status
-
停止服务:
/sbin/service rabbitmq-server stop
-
开启 web 管理插件:
rabbitmq-plugins enable rabbitmq_management
, 然后再浏览器中输入当前IP + 15672端口号即可访问,默认账号:guest,密码:guest。登录会发现出现以下问题:出现下面问题按照添加用户命令执行即可,然后使用添加的用户登录。
-
开启应用:
rabbitmqctl stop_start
-
关闭应用:
rabbitmqctl stop_app
添加用户命令
-
创建账号:
rabbitmqctl add_user 账号 密码
-
设置用户角色:
rabbitmqctl set_user_tags 账号 administrator
-
设置用户权限:
rabbitmqctl set_permissions -p "/" 账号 ".*" ".*" ".*"
-
获取用户和角色:
rabbitmqctl list_users
RabbitMq搭建集群
克隆出来两台一样的虚拟机,如下图所示
修改三台服务器的主机名称
-
vi /etc/hostname
-
分别修改为:node1、node2、node3
配置各个节点的 hosts 文件,让各个节点都能互相识别对方
-
vi /etc/hosts
-
分别在三个服务器的host文件中添加以下配置
192.168.85.129 node1
192.168.85.130 node2
192.168.85.131 node3
以确保各个节点的 cookie 文件使用的是同一个值
在 node1
节点上执行远程操作命令
scp /var/lib/rabbitmq/.erlang.cookie root@node2:/var/lib/rabbitmq/.erlang.cookie
scp /var/lib/rabbitmq/.erlang.cookie root@node3:/var/lib/rabbitmq/.erlang.cookie
启动 RabbitMQ 服务,顺带启动 Erlang 虚拟机和 RbbitMQ 应用服务 在三台节点上分别执行以下命令:
rabbitmq-server -detached
在 node2
、node3
节点上执行以下命令:
注意:(rabbitmqctl stop
会将Erlang 虚拟机关闭,rabbitmqctl stop_app
只关闭 RabbitMQ 服务) 记得关闭防火墙
1. rabbitmqctl stop_app
2. rabbitmqctl reset
3. rabbitmqctl join_cluster rabbit@node1
4. rabbitmqctl start_app (只启动应用服务)
查看集群状态
rabbitmqctl cluster_status
需要重新设置用户
-
创建账号:
rabbitmqctl add_user 账号 密码
-
设置用户角色:
rabbitmqctl set_user_tags 账号 administrator
-
设置用户权限:
rabbitmqctl set_permissions -p "/" 账号 ".*" ".*" ".*"
使用上面创建的账号随便访问三台地址都可访问了,如图所示:有三个节点
解除集群节点(node2 和 node3 机器分别执行 - 选择执行)
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
rabbitmqctl cluster_status
rabbitmqctl forget_cluster_node rabbit@node2 (node1 机器上执行)
上面这些,已经搭建好了集群但是不可复用,意思就是我在 node1节点上生成的消息 node2和node3没有,假如node1宕机了那消息就会丢失,所以就需要用到 镜像队列。
镜像队列
引入镜像队列(Mirror Queue)的机制,可以将队列镜像到集群中的其他 Broker 节点之上,如果集群中的一个节点失效了,队列能自动地切换到镜像中的另一个节点上以保证服务的可用性。
搭建步骤
-
在 node1、node2、node3 任意节点上添加以下策略:
-
在给 node1 上发送一条消息 注意名称要符合上图的规则,上图队列名称是以 hello开头的。
-
停掉 node1 之后发现 node2 成为镜像队列
就算整个集群只剩下一台机器了 依然能消费队列里面的消息说明队列里面的消息被镜像队列传递到相应机器里面了
生产者代码
/**
* 队列名称
*/
public static final String QUEUE_NAME = "hello";
/**
* 普通生产者
*/
public static void normalProducer() throws Exception {
// 创建一个连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 工厂IP 连接RabbitMq的队列
factory.setHost("192.168.85.129");
// 用户名
factory.setUsername("zjh");
// 密码
factory.setPassword("zjh");
// 创建连接
Connection connection = factory.newConnection();
// 获取信道
Channel channel = connection.createChannel();
/*
生成一个队列
1.队列名称
2.队列里面的消息是否持久化,默认情况消息存储在内存中
3.该队列是否只提供一个消费者进行消费 是否进行消息共享,true可以多个消费者消费
4.是否自动删除 最后一个消费者断开连接以后 该队列是否自动删除 true自动删除 false不自动删除
5.其他参数
*/
channel.queueDeclare(QUEUE_NAME, true, false, false, null);
// 发消息 初次使用
String message = "hello world";
/*
发送一个消费
1.发送到哪个交换机
2.路由的Key是哪个,本次队列的名称
3.其他的参数信息
4.发送消息的消息体
*/
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println("消息发送完毕");
}
消费者代码
/**
* 队列名称
*/
public static final String QUEUE_NAME = "hello";
/**
* 接收消息
*/
public static void main(String[] args) throws Exception {
// 创建一个连接工厂
ConnectionFactory factory = new ConnectionFactory();
// 工厂IP 连接RabbitMq的队列
factory.setHost("192.168.85.130");
// 用户名
factory.setUsername("zjh");
// 密码
factory.setPassword("zjh");
// 创建连接
Connection connection = factory.newConnection();
// 获取信道
Channel channel = connection.createChannel();
// 声明接收消息回调
DeliverCallback deliverCallback = (consumerTag, message) -> System.out.println(new String(message.getBody()));
// 声明取消接收消息回调
CancelCallback cancelCallback = consumerTag -> System.out.println("消息消费被中断");
/*
消费者消费信息
1.消费哪个队列
2.消费成功之后是否要自动应答 true代表自动应答 false代表手动应答
3.消费者未成功消费的回调
4.消费者取消消费的回调
*/
channel.basicConsume(QUEUE_NAME, true, deliverCallback, cancelCallback);
}
测试结果
可以看到代码中,消费者和生产者的连接ip是不同的,因为发送的消息到 node1 节点上之后需要将 node1 节点停掉,然后消费 node2 或者 node3 节点其目的就是为了测试镜像队列,查看是否备份到了其他机器消息是否丢失,如果成功消费说明备份成功消息未丢失。这样做的话坏处也很明显,就是如果宕机了不能及时更改,就需要借助下方负载均衡实现。
Haproxy 实现负载均衡
Haproxy 提供高可用性、负载均衡及基于TCPHTTP 应用的代理,支持虚拟主机,它是免费、快速并且可靠的一种解决方案,包括 Twitter,Reddit,StackOverflow,GitHub 在内的多家知名互联网公司在使用。Haproxy 实现了一种事件驱动、单一进程模型,此模型支持非常大的井发连接数。
扩展 nginx,lvs,haproxy 之间的区别: http://www.ha97.com/5646.html
注意事项
最好是在新节点上搭建,不要图方便再原有的 rabbitmq
节点上搭建,不然可能会出现以下错误
linux
服务器需要关闭:selinux
、firewalld
selinux
是什么?有啥用?如何开启和关闭?
- 它叫做 "安全增强型Linux(Security-Enhanced Linux)",简称 SELinux,它是 Linux 的一个安全子系统。
- 其主要作用就是最大限度地减小系统中服务进程可访问的资源(根据的是最小权限原则)。避免权限过大的角色给系统带来灾难性的结果。
# 查看selinux状态
getenforce
# 临时关闭 selinux
setenforce 0
# 永久关闭selinux
vi /etc/selinux/config
将 SELINUX=enforcing 改为 SELINUX=disabled
# 查看firewalld状态
systemctl status firewalld
# 关闭
systemctl stop firewalld
# 关闭开机自启
systemctl disable firewalld
安装
yum install -y haproxy
直接编辑(使用yum安装后的haproxy的配置文件在 /etc/haproxy/haproxy.cfg
)
编辑文件
vi /etc/haproxy/haproxy.cfg
编辑内容
直接将以下内容复制进去就行,然后把 ip地址
改下,就ok
#---------------------------------------------------------------------
# Example configuration for a possible web application. See the
# full configuration options online.
#
# http://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2 # 定义全局的syslog服务器。日志服务器需要开启UDP协议,最多可以定义两个。基于syslog记录日志到指定设备,级别有(err、warning、info、debug)
chroot /var/lib/haproxy # 锁定haproxy的运行目录,把haproxy的进程禁锢在一个文件夹内
pidfile /var/run/haproxy.pid # 指定haproxy的pid文件存放路径,启动进程的用户必须有权限访问此文件。要和service指定的pid路径一样
maxconn 4000 # 每个haproxy进程的最大并发连接数,默认4000,可以是100000,还可以更大:一百万
user haproxy # 默认用户
group haproxy # 默认组
daemon # 以后台守护进程的方式运行
# turn on stats unix socket
stats socket /var/lib/haproxy/stats # 创建监控所用的套接字目录
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode http # 默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK。后面listen的优先级比默认高,可以单独设置。
log global
option httplog
option dontlognull # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器
option http-server-close # 每次请求完毕后主动关闭http通道
option forwardfor except 127.0.0.0/8
option redispatch # serverId对应的服务器挂掉后,强制定向到其他健康的服务器,重新派发
retries 3 # 3次连接失败就认为服务不可用
timeout http-request 10s
timeout queue 1m
timeout connect 10s # 客户端请求从haproxy到后端server最长连接等待时间(TCP连接之前),默认单位ms
timeout client 1m # 设置haproxy与客户端的最长非活动时间,默认单位ms,建议和timeout server相同
timeout server 1m # 客户端请求从haproxy到后端服务端的请求处理超时时长(TCP连接之后),默认单位ms,如果超时,会出现502错误,此值建议设置较大些,访止502错误。
timeout http-keep-alive 10s # session会话保持超时时间,此时间段内会转发到相同的后端服务器
timeout check 10s # 对后端服务器的默认检测超时时间
maxconn 3000 # 最大连接数
#
# haproxy 管理页面
#
listen admin_stats *:8090 #为 haproxy 访问状态监控页面配置,取名为 admin_stats,端口号自定义
stats enable #启用监听端口
mode http #http的7层模式
log global #继承global中log的定义
stats uri /stats #监控页面的url访问路径,即 http://ip/stats 访问监控页面
stats realm Haproxy\ Statistics #监控页面的密码框提示信息
stats auth admin:admin #监控页面的用户和密码,可以设置多个用户名
stats admin if TRUE #当通过认证才可管理
stats refresh 30s #页面自动刷新时间30s
#
# rabbitmq web页面访问,当前ip + 15672就可以访问
# check inter 2000 每隔2s检测一次,fall 5是5次失败认为服务器不可用
#
listen rabbitmq_admin
bind 0.0.0.0:15672
mode http #配置HTTP模式
option httplog
balance roundrobin #简单的轮询
server node1 192.168.85.129:15672 check check inter 2000 fall 5
server node2 192.168.85.130:15672 check check inter 2000 fall 5
server node3 192.168.85.131:15672 check check inter 2000 fall 5
#
# rabbitmq 集群
#
listen rabbitmq_cluster
bind 0.0.0.0:5672
mode tcp #配置TCP模式
option tcplog
balance roundrobin #简单的轮询
server rabbitmq-node1 192.168.85.129:5672 check check inter 2000 fall 5
server rabbitmq-node2 192.168.85.130:5672 check check inter 2000 fall 5
server rabbitmq-node3 192.168.85.131:5672 check check inter 2000 fall 5
haproxy rsyslog日志配置
# 编辑此文件
vi /etc/rsyslog.conf
# 在文件的最后一行,加上:
local2.* /var/log/haproxy/rabbitmq.log
重启日志服务 + 启动haproxy代理服务
# 重启日志服务
systemctl restart rsyslog.service
# 启动haproxy。其中 -f 代表指定配置文件的路径。
haproxy -f /etc/haproxy/haproxy.cfg
# 重新启动haproxy
haproxy -f /etc/haproxy/haproxy.cfg -st `cat /var/run/haproxy.pid`
# 停止haproxy
kill -9 `cat /var/run/haproxy.pid`
# 查看haproxy启动的端口
ss -nplt | grep haproxy
可能会出现以下警告,可以忽略。
访问 haproxy 管理页面
http://ip:8090/stats
访问 rabbitmq web界面
http://ip:15672/
测试步骤
-
还是上方的生产者和消费者代码,生产者代码不变启动发送消息,如下图所示:
-
然后我们将生产者连接的服务器给关闭了,将消费者的地址改为安装了 haproxy 的服务器ip 进行消费,如下图所示消费成功。
如果我们负载均衡服务器挂掉了,那就会导致所有的rabbitmq服务器都不可用,就需要借助 Keepalived
Keepalived 引用于 https://blog.csdn.net/want_you_gogo/article/details/127285107
Keepalived 主备
用keepalived做主备,避免单点问题、实现高可用。在 192.168.85.132(主)、192.168.85.133(备) 节点上分别安装Keepalived。
安装相关命令
# 安装
yum install -y keepalived
# 备份原有配置
cp /etc/keepalived/keepalived.conf{,.bak}
# 配置Keepalived
vi /etc/keepalived/keepalived.conf
编辑 192.168.85.132 机器
! Configuration File for keepalived
# keepalived全局配置
global_defs {
#每个keepalived节点的唯一标识,不能与备机相同。
router_id keepalived_master
}
# 检测 Haproxy 脚本
vrrp_script check_haproxy {
script "/etc/keepalived/haproxy_check.sh" #脚本所在的目录
interval 10 #检测 haproxy 心跳频率:每隔10秒检测一次
weight 11 #权重
}
# 虚拟路由器配置
vrrp_instance haproxy {
state MASTER # 设置虚拟路由器状态为MASTER,表示为主。
interface ens33 # 绑定当前虚拟路由器所使用的物理网卡,如eth0、bond0等,可通过 ifconfig 获得。
virtual_router_id 51 # 每个虚拟路由器的唯一标识。同属一个虚拟路由器的多个keepalived节点必须相同,务必要确保在同一网络中此值唯一。
priority 90 # 当前物理节点在此虚拟路由器中的优先级,值越大优先级越高。注意:主机的优先权要比备机高。
advert_int 1 # 心跳检查频率,单位:秒。
# 认证机制
authentication {
auth_type PASS # 认证类型
auth_pass 1111 # 秘钥,同一虚拟路由器的多个 keepalived 节点 auth_pass 值必须保持一致
}
# 虚拟路由器的VIP,不指定网卡时默认添加在eth0上。在添加VIP地址时,需确保将要使用的VIP不存在,避免冲突。
virtual_ipaddress {
192.168.85.140 # 对外开放的虚拟ip
}
# 调用检测 haproxy 的脚本
track_script {
check_haproxy
}
}
编辑 192.168.85.133 机器
! Configuration File for keepalived
# keepalived全局配置
global_defs {
# 每个keepalived节点的唯一标识,不能与备机相同。
router_id keepalived_backup
}
#检测 Haproxy 脚本
vrrp_script check_haproxy {
script "/etc/keepalived/haproxy_check.sh" # 脚本所在的目录
interval 10 # 检测 haproxy 心跳频率:每隔10秒检测一次
weight 11 # 权重
}
#虚拟路由器配置
vrrp_instance haproxy {
state BACKUP # 设置虚拟路由器状态为BACKUP,表示为备。
interface ens33 # 绑定当前虚拟路由器所使用的物理网卡,如eth0、bond0等,可通过 ifconfig 获得。
virtual_router_id 51 # 每个虚拟路由器的唯一标识。同属一个虚拟路由器的多个keepalived节点必须相同,务必要确保在同一网络中此值唯一。
priority 80 # 当前物理节点在此虚拟路由器中的优先级,值越大优先级越高。注意:主机的优先权要比备机高。
advert_int 1 # 心跳检查频率,单位:秒。
# 认证机制
authentication {
auth_type PASS # 认证类型
auth_pass 1111 # 秘钥,同一虚拟路由器的多个 keepalived 节点 auth_pass 值必须保持一致
}
# 虚拟路由器的VIP,不指定网卡时默认添加在eth0上。在添加VIP地址时,需确保将要使用的VIP不存在,避免冲突。
virtual_ipaddress {
192.168.85.140 # 对外开放的虚拟ip
}
# 调用检测 haproxy 的脚本
track_script {
check_haproxy
}
}
详细的keepalived配置可参考:https://blog.51cto.com/johnnyfang/5419017
编写 haproxy 检测脚本
脚本作用:检测
haproxy
服务,如果haproxy
服务挂了则先尝试自动重启haproxy
服务;如果重启不成功,则关闭Keepalived
服务并切换到backup。
注意:两台 haproxy 服务器都要编写以下内容
# 编辑文件
vi /etc/keepalived/haproxy_check.sh
#!/bin/bash
#haproxy存活检测脚本
#当发现haproxy服务挂掉时,先自动重启haproxy的服务,如果启动不成功则关闭当前节点的Keepalived服务,并将虚拟vip飘到备用节点上。
#-----------全局变量------------
# 本机ip
localIP=`ip a|grep inet|grep global|grep brd|head -n 1|awk '{printf $2}'|cut -d "/" -f1`
# backup节点ip
backupIP="192.168.85.133"
# haproxy 服务存活检测
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ]; then
# 记录日志
echo "检测到节点${localIP}的HAProxy服务挂掉,正在尝试重启中..." >> /etc/keepalived/keepalived.log
# 重启haproxy服务
haproxy -f /etc/haproxy/haproxy.cfg
sleep 2s
# haproxy 自动重启成功
if [ $(ps -C haproxy --no-header | wc -l) -eq 1 ]; then
echo "检测到节点${localIP}的HAProxy服务挂掉,正在尝试重启中...重启成功!" >> /etc/keepalived/keepalived.log
fi
fi
# 这里最好休眠2s等待haproxy启动成功,不然下面的判断有可能还会出现找不到haproxy服务进程的情况
# 注意:这个sleep时间一定要比keepalived.conf配置里"检测 haproxy 心跳频率:interval 10"设置的时间要短,否则将卡在sleep这!
sleep 2s
# 自动重启不成功,进行vip切换操作,邮件+短信通知
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ];then
echo "检测到节点${localIP}的haproxy服务挂掉,尝试重启失败,停掉此节点上的keepalived服务,虚拟vip将飘到backup节点:${backupIP}" >> /etc/keepalived/keepalived.log
# 停止 keealived 服务
service keepalived stop
fi
给脚本添加权限
chmod +x /etc/keepalived/haproxy_check.sh
创建日志文件名称
# 编辑文件名
vi /etc/keepalived/keepalived.log
# 保存
:wq
启动keepalived的服务
启动顺序:先启动master节点服务,再启动backup节点的服务。
# 启动keepalived服务
service keepalived start
# 查看keepalived状态
service keepalived status
#查看keepalived启动日志:
journalctl -xe
#查看keepalived日志
tail -f /var/log/messages
#停掉keepalived服务
service keepalived stop
- 在master上查看主机ip信息
可知绑定在 ens33 上的vip正常出现在master节点上,且主机 ip 多出了一个 192.168.85.140(配置文件中默认添加的虚拟VIP地址),而且也能ping通。
- 在backup上查看主机ip信息则没有此虚拟ip
测试vip
(虚拟ip:192.168.85.140)是否可用
使用 vip(虚拟ip:192.168.85.140) 访问
Rabbitmq
管理平台和haproxy
监控平台
测试vip飘移(主备切换)
# 启动 haproxy 服务
haproxy -f /etc/haproxy/haproxy.cfg
# 停止 kaproxy 服务
kill -9 `cat /var/run/haproxy.pid`
# 重新启动 haproxy 服务
haproxy -f /etc/haproxy/haproxy.cfg -st `cat /var/run/haproxy.pid`
# 查看 haproxy 服务状态
ss -nplt | grep haproxy
# 启动 keepalived 服务
service keepalived start
# 查看 keepalived 服务状态
service keepalived status
# 停止 keepalived 服务
service keepalived stop
- 关闭 master 节点(192.168.85.132) 的 haproxy 服务:
此时, keepalived 每隔 10s 触发一次的haproxy心跳检测脚本haproxy_check.sh里自动恢复了 master 节点的 haproxy 服务。虚拟 ip 没有飘到 backup 节点:
- 模拟 master 节点的 haproxy 服务无法自动恢复时
再次 kill 掉 master 节点的 haproxy 服务:
结论:虚拟 ip 能在主备上自动切换,切换后 vip 自动从 master 上飘到 backup 上
- 飘移后继续测试vip是否可用:
http://192.168.85.140:15672
http://192.168.85.140:8090/stats
结论:用虚拟ip(192.168.85.140)访问 haproxy 监控统计平台和 RabbitMQ 管理平台,依然能访问成功!
- 恢复 master(启动haproxy、keepalived),看看 vip 能否飘回来
结论:当 master 节点恢复后,vip 自动飘回 master 节点!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)