基于docke搭建多台服务器rabbitmq集群
可以参考这篇文章
dokcer拉取rabbitmq镜像之后
机器1
docker run -d --hostname rabbitmq1 --add-host=rabbitmq2:192.168.23.189 --restart=unless-stopped --name rabbitmq1 --net host -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -e RABBITMQ_ERLANG_COOKIE='rabbit_mq' rabbitmq:management
-d 容器后台运行
--hostname rabbitmq1 容器的主机名为 rabbitmq1
--add-host="rabbitmq1":192.168.23.189 修改容器内部的hosts
--restart=unless-stopped docker 容器重启后重启MQ
--name rabbitmq1 容器名为rabbitma1,在宿主机上运行“docker ps”命令时显示的名称
-p "5672:5672" 消息通讯端口
-p "15672:15672" 后台管理端口
-e RABBITMQ_DEFAULT_USER=admin 设置rabbitmq默认用户为admin
-e RABBITMQ_DEFAULT_PASS=admin 设置rabbitmq默认密码为admin
-e RABBITMQ_ERLANG_COOKIE='rabbit_mq' 设置rabbitmq的cookie为“rabbit_mq”,可以自定义为其他文本,容器保持一致即可
机器2
docker run -d --hostname rabbitmq2 --add-host=rabbitmq1:192.168.23.188 --restart=unless-stopped --name rabbitmq2 --net host -p 15672:15672 -p 5672:5672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -e RABBITMQ_ERLANG_COOKIE='rabbit_mq' rabbitmq:management
安装后可以在网页打开了
机器1:
进入rabbitmq容器
#首先停止当前MQ
rabbitmqctl stop_app
#resetMQ
rabbitmqctl reset
#重新启动MQ
rabbitmqctl start_app
退出容器
exit
机器2
进入容器
#首先停止当前MQ
rabbitmqctl stop_app
#resetMQ
rabbitmqctl reset
#跟机器1的消息队列建立关系
rabbitmqctl join_cluster --ram rabbit@rabbitmq1
#重新启动MQ
rabbitmqctl start_app
退出容器
exit
到这里我们的集群搭建完成
我们还可以创建更多的机器依赖在机器1或者机器2
1.镜像队列
1. 使用镜像的原因 如果 RabbitMQ 集群中只有一个 Broker 节点,那么该节点的失效将导致整体服务的临时性不可用,并 且也可能会导致消息的丢失。可以将所有消息都设置为持久化,并且对应队列的durable属性也设置为true, 但是这样仍然无法避免由于缓存导致的问题:因为消息在发送之后和被写入磁盘井执行刷盘动作之间存在 一个短暂却会产生问题的时间窗。通过 publisherconfirm 机制能够确保客户端知道哪些消息己经存入磁盘, 尽管如此,一般不希望遇到因单点故障导致的服务不可用。 引入镜像队列(Mirror Queue)的机制,可以将队列镜像到集群中的其他 Broker 节点之上,如果集群中 的一个节点失效了,队列能自动地切换到镜像中的另一个节点上以保证服务的可用性。
我们新建一个链接在113节点的队列
public class Producer {
//队列名称
private final static String QUEUE_NAME="dfp_1";
public static void main(String[] args) throws IOException, TimeoutException {
/**
* //创建一个工厂链接
* 设置mq安装的地址
* 登录的账号
* 登录的密码
*/
ConnectionFactory factory=new ConnectionFactory();
// factory.setHost("192.168.1.111");
// factory.setUsername("guest");
// factory.setPassword("guest");
/**
* 113节点
*/
factory.setHost("192.168.1.113");
factory.setUsername("admin");
factory.setPassword("123456");
//channel实现自动close接口自动关闭,不需要显示
// 创建连接
Connection connection= factory.newConnection();
// 创建信道
Channel channel= connection.createChannel();
/**
* 生成一个队列
* 1.队列名称
* 2.队列里面的消息是非持久化,默认消息存放在内存中
* 3.该队列是否提供一个消费者进行消费,是否决定共享true可以多个消费者消费
* 4.是否自动删除,最后一个消费者断开后,该队列是否自动删除。true自动删除
* 5.其他参数
*/
channel.queueDeclare(QUEUE_NAME,false,false,false,null);
String msg="hello,dfp";
/**
* 发送一个消息
* 1.发送到交换机的位置
* 2.路由的key是哪个
* 3.其他参数
* 4.发送的消息体
*/
channel.basicPublish("",QUEUE_NAME,null,msg.getBytes());//二进制传输
System.out.println("消息发送完毕"+msg);
}
}
有一个属于r1的队列
先发送消息 不用消费者接收
此时服务器又一个消息等待消费,我们直接关闭服务器
我们手动关闭r1节点在运行程序
r1服务器关闭 我们在运行消费者程序无法打印内容
我们重启r1服务器
消息消失并且消费者不可以打印内容。
这样就突出 镜像队列备份的作用
设置镜像备份
最后点击添加
这个时候dfp开头的队列 就会属于2个队列,这样机器r1死机看看消息会不会消失
先启动生产者---再关机R1---在启动消费者
启动消费者 消费dfp_1队列
我们是可以拿到数据的
我们在看 dfp122队列是远不会丢失数据
2.Haproxy+Keepalive实现高可用负载均衡
大家可以去了解一些这里不详细实现讲述一下原理
在请求之前我们建立一个 Haproxy+Keepalive作为转发的中间件,当访问级别特别大达到千万级2个happroxy会实现负载均衡,并且当一个断开的时候另一个会继续工作并且会一直请求另一个机器判断是否重启。并且消息过来之后可以转发到集群的任意一个rabbitmq做处理,不至于一个机器处理大量消息另一个机器怠工
3.Federation Exchange联邦交换机
应用场景
(broker 北京),(broker 深圳)彼此之间相距甚远,网络延迟是一个不得不面对的问题。有一个在北京 的业务(Client 北京) 需要连接(broker 北京),向其中的交换器 exchangeA 发送消息,此时的网络延迟很小, (Client 北京)可以迅速将消息发送至 exchangeA 中,就算在开启了 publisherconfirm 机制或者事务机制的 情况下,也可以迅速收到确认信息。此时又有个在深圳的业务(Client 深圳)需要向 exchangeA 发送消息, 那么(Client 深圳) (broker 北京)之间有很大的网络延迟,(Client 深圳) 将发送消息至 exchangeA 会经历一 定的延迟,尤其是在开启了publisherconfirm 机制或者事务机制的情况下,(Client 深圳) 会等待很长的延 迟时间来接收(broker 北京)的确认信息,进而必然造成这条发送线程的性能降低,甚至造成一定程度上的 阻塞。
将业务(Client 深圳)部署到北京的机房可以解决这个问题,但是如果(Client 深圳)调用的另些服务都部 署在深圳,那么又会引发新的时延问题,总不见得将所有业务全部部署在一个机房,那么容灾又何以实现? 这里使用 Federation 插件就可以很好地解决这个问题。
简单的来说就是一个公司 有2个服务器 一个在深圳一个在北京,就近原则我在广州访问这个公司的数据我访问该公司的深圳服务肯定快很多,但是对于公司而言要做到北京和深圳的数据相互同步。这就引用到联邦交换机
在集群服务器上安装插件
rabbitmq-plugins enable rabbitmq_federation rabbitmq-plugins enable rabbitmq_federation_management
成功之后
根据这个原理来设置联邦交换机
声明联邦交换机和队列
添加上下游配置 node1作为上游的节点
填写前2个就可以 name是上游名称
uri是 固定格式 amqp://【mq账户】:【mq密码】@【节点名称】
节点名称参考这里的@xxx
配置下游策略
表示成功
既然有联邦交换机就会有联邦队列
我们在配置策略的时候中 我们设置同一个上游节点node1-as-up根据上面的设置方式相似
我们只需要重新设置一个下游策略将策略的实施方式改为队列即可 如下
这样一个联邦队列就设置完成了,我们不仅仅可以通过交换机同步2个节点的信息也可用队列来实现同步
自此 尚硅谷的rabbitmq学习完成了 资料源于尚硅谷感谢开源