为什么搭建rabbitmq集群?
rabbitmq集群有那些模式?
如何搭建Rabbitmq集群?
rabbitmq镜像高可用策略有那些?
RabbitMQ这款产品本身的优点众多,大家最看好的便是他的异步化提高系统抗峰值能力,然后便是系统及功能结构解耦,既然它如此重要,那么我们就需要考虑它的高可用性。
rabbitmq有3种模式:
单一模式:即单机情况不做集群,就单独运行一个rabbitmq而已,生产上肯定不能用。
普通模式:普通集群就是在多台机器上启动多个实例。每个队列只会存在其中的一个实例上,然后所有实例同步这些队列的元数据。消费者在进行消费的时候,如果连接的实例上恰好不是队列所在的实例,就会根据队列的元数据去队列所在实例上拉取数据
由此可知,集群模式并没做到分布式,如果队列所在的实例宕机了,会导致接下来其他实例就无法从那个实例拉取消息,所以集群主要是提高吞吐量的
镜像模式:把需要的队列做成镜像队列,存在与多个节点属于**RabbitMQ的HA方案。**该模式解决了普通模式中的问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在客户端取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用。
参考:https://www.rabbitmq.com/ha.html
两台Centos7的机器,hostname分别为:A, B
IP地址分别为:A:10.0.0.22;B:10.0.0.33
修改hosts文件如下,下面是A这台机器的hosts文件内容,B也是需要如下配置:
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.22 A
10.0.0.33 B
保证两台机器都能够相互ping通
ping A 保证ping通
ping B 保证ping通
把rabbitmq分别装在2台机器上
在上述的两台机器上安装rabbitmq完成之后,你可以看到你的机器中有如下1个文件。路径在 H O M E 中 或 者 在 / v a r / l i b / r a b b i t m q 中 , 文 件 名 称 为 . e r l a n g . c o o k i e , 他 是 一 个 隐 藏 文 件 。 我 的 在 HOME中或者在/var/lib/rabbitmq中,文件名称为.erlang.cookie,他是一个隐藏文件。我的在 HOME中或者在/var/lib/rabbitmq中,文件名称为.erlang.cookie,他是一个隐藏文件。我的在HOME下,也就是/root.
RabbitMQ的集群是依赖erlang集群,而erlang集群是通过这个cookie进行通信认证的,因此我们做集群的第一步就是干cookie。
必须使集群中也就是A,B这两台机器的.erlang.cookie文件中cookie值一致,且权限为owner只读,修改权限:
chmod 600 .erlang.cookie #修改权限,只有自己读写
scp /root/.erlang.cookie 10.0.0.33:/root #保证两台服务器cookie一样
停止MQ服务
rabbitmqctl stop
组件集群,执行启动命令,后续启动集群使用此命令
rabbitmq-server -detached
slave加入集群操作(重新加入集群也是如此,以最开始的主节点为加入节点)
A为主节点master,所以我们不管。
B节点:
rabbitmqctl stop_app #停止当前节点
#成功之后出现Clustering node rabbit@B with rabbit@A
rabbitmqctl join_cluster --ram rabbit@A #加入集群 --ram内存存储,默认不加的话就是磁盘存储
rabbitmqctl start_app #再次重启当前节点
#。。。。。如果还有多个节点一次重复上面这个步骤就可以了
其他命令
#默认为第一个node名称(在任意节点修改都可以)
rabbitmqctl set_cluster_name rabbitmq_cluster1
#在另外其他节点上操作要移除的集群节点
rabbitmqctl forget_cluster_node rabbit@B
我们打开控制台可以看到overview下的Nodes已经有两个节点了,如此便可以啦,你可以做下测试,验证下我们说的普通模式。
先镜像模式要依赖policy模块,这个模块是做什么用的呢?
policy中文来说是政策,策略的意思,那么他就是要设置,那些Exchanges或者queue的数据需要复制,同步,如何复制同步?对就是做这些的。
PS:设置镜像队列策略(在任意一个节点上执行)
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
PS:将所有队列设置为镜像队列,即队列会被复制到各个节点,各个节点状态一致,RabbitMQ高可用集群就已经搭建好了,我们可以重启服务,查看其队列是否在从节点同步。
参数意思为:
ha-all:为策略名称。
:为匹配符,只有一个代表匹配所有,^abc为匹配名称为abc的exchanges或者queue。
ha-mode:为匹配类型,他分为3种模式:all-所有(所有的queue),exctly-部分(需配置ha-params参数,此参数为int类型比如3,众多集群中的随机3台机器),nodes-指定(需配置ha-params参数,此参数为数组类型比如[“3rabbit@F”,“rabbit@G”]这样指定为F与G这2台机器。)。
具体可参考http://www.rabbitmq.com/ha.html
yml配置:
spring:
application:
name: zoo-plus-cluster
rabbitmq:
virtual-host: /
username: xiefei
password: xiefei
addresses: 10.0.0.22:5672,10.0.0.33:5672
connection-timeout: 15000
添加一个队列:
/**
* @author: 谢飞
*/
@Configuration
public class RabbitConfig {
@Bean
public Queue helloQueue() {
return QueueBuilder.durable("hello-queue").build();
}
}
消费者:
/**
* @author: 谢飞
*/
@Slf4j
@Component
public class Consumer {
@RabbitListener(queues = {"hello-queue"})
public void helloQueue(Message message, Channel channel) {
log.info("-----------------hello-queue消费:" + new String(message.getBody()));
}
}
测试:
/**
* @author: 谢飞
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestRabbitMQ {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送到集群队列
*/
@Test
public void sendHelloQueue() {
rabbitTemplate.convertAndSend( "hello-queue", "这是发送到集群队列的消息");
}
}
源码地址:https://gitee.com/zoo-plus/springboot-learn/tree/2.x/springboot-middleware/rabbitmq-cluster
PS:我们可以使用Ha-Proxy(负载均衡)+Keepalived(单点故障)来实现高可用。
HAProxy:
是一款提供高可用性、负载均衡以及基于TCP和HTTP应用的代理软件,HAProxy是完全免费的、借助HAProxy可以快速并且可靠的提供基于TCP和HTTP应用的代理解决方案。
HAProxy适用于那些负载较大的web站点,这些站点通常又需要会话保持或七层处理。
HAProxy可以支持数以万计的并发连接,并且HAProxy的运行模式使得它可以很简单安全的整合进架构中,同时可以保护web服务器不被暴露到网络上。
Keepalived:
它是一个高性能的服务器高可用或热备解决方案,Keepalived主要来防止服务器单点故障的发生问题,可以通过其与Nginx、Haproxy等反向代理的负载均衡服务器配合实现web服务端的高可用。Keepalived以VRRP协议为实现基础,用VRRP协议来实现高可用性(HA).VRRP(Virtual Router Redundancy Protocol)协议是用于实现路由器冗余的协议,VRRP协议将两台或多台路由器设备虚拟成一个设备,对外提供虚拟路由器IP(一个或多个)。