SpringBoot整合RabbitMQ消息中间件及多种设计模式


1、介绍与安装下载

1.1、不同MQ特点

不同MQ特点

1.2、下载

步骤一
步骤二
下载

1.3、打开网址

RabbitMQ成功运行本地打开网址
账号密码都:guest
运行成功的样子

2、使用可视化配置

2.1、创建交换机

创建交换机

2.2、创建队列

队列要绑定交换机
创建队列
删除队列
删除队列

2.3、来宾用户详情

来宾用户

2.4、创建来宾用户

创建来宾用户

2.5、用户与虚拟主机进行绑定

绑定

代表可访问的虚拟主机

2.6、创建虚拟主机

创建虚拟主机
通信端口

3、五种常用的模式

3.1、导入依赖

        <!--    导入rabbitmq依赖-->
        <dependency>
            <groupId>com.rabbitmq</groupId>
            <artifactId>amqp-client</artifactId>
            <version>5.7.2</version>
        </dependency>

3.2、连接工具类

public class RabbitMqUtils {

    private static ConnectionFactory factory;

    static {
        factory = new ConnectionFactory();
        factory.setHost("127.0.0.1");
        factory.setPort(5672);
        factory.setVirtualHost("/ems");
        factory.setUsername("ems");
        factory.setPassword("ems");
    }

    /**
     * 定义提供连接对象的方法
     * @return
     */
    public static Connection getConnection() {
        try {
            Connection connection = factory.newConnection();
            return connection;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 关闭连接   注意:一般消费者不用关闭连接 只用于生产者关闭连接
     *
     * @param channel
     * @param connection
     */
    public static void closeConnection(Channel channel, Connection connection) {
        try {
            if (channel != null) {
                channel.close();
            }
            if (connection != null) {
                connection.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.3、第一种模式(HelloWorld)

图解

    //生产消息
    public void testSendMessage() throws IOException, TimeoutException {
        /*
        //创建连接mq的连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        //设置连接rabbitmq主机
        connectionFactory.setHost("127.0.0.1");
        //设置端口号
        connectionFactory.setPort(5672);
        //设置连接那个虚拟主机
        connectionFactory.setVirtualHost("/ems");
        //设置访问虚拟主机的用户名和密码
        connectionFactory.setUsername("ems");
        connectionFactory.setPassword("ems");
        //获取连接对象
        Connection connection = connectionFactory.newConnection();
        */

        //通过工具类获取连接对象
        Connection connection = RabbitMqUtils.getConnection();
        //获取连接中通道
        Channel channel = connection.createChannel();

        //通道绑定对应消息队列(通道中存放的是消息)
        //参数1:队列名称,如果队列不存在则自动创建
        //参数2:用来定义队列特征是否要持久化
        //参数3:是否独占队列(true 就只能被当前连接使用)
        //参数4:是否在消费完成后自动删除队列
        //参数5:额外附加参数
        channel.queueDeclare("hello", false, false, false, null);

        //发布消息
        //参数1:交换机名称
        //参数2:队列的名称
        //参数3:传递消息额外设置
        //参数4:发布消息时的具体内容
        channel.basicPublish("", "hello", null, "hello rabbitmq".getBytes());

        /*channel.close();
        connection.close();*/
        //使用工具类关闭
        RabbitMqUtils.closeConnection(channel,connection);
    }
	//消费者
    public static void main(String[] args) throws IOException, TimeoutException {
        /*
        //创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("127.0.0.1");
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/ems");
        connectionFactory.setUsername("ems");
        connectionFactory.setPassword("ems");
        Connection connection = connectionFactory.newConnection();
        */
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();
        //生产者和消费者的参数要严格对应上
        channel.queueDeclare("hello", false, false, false, null);
        //消费消息
        //参数1:消费那个队列的消息,消息名称
        //参数2:开始消息的自动确认机制
        //参数3:消费时的回调接口
        channel.basicConsume("hello", true, new DefaultConsumer(channel) {
            //最后一个参数:消息队列中取出的消息
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("new String(body) = " + new String(body));
            }
        });
        //为了保持运行不能关闭
        //channel.close();
        //connection.close();
    }

3.4、第二种模式(work quene)

Work queues,也被称为(Task queues),任务模型。当消息处理比较耗时的时候,可能生产消息的速度会远远大于消息的消费速度。长此以往,消息就会堆积越来越多,无法及时处理。此时就可以使用work模型:让多个消费者绑定到一个队列,共同消费队列中的消息。队列中的消息一旦消费,就会消失,因此任务是不会被重复执行的。
图解

  1. 开发生产者
    public static void main(String[] args) throws IOException {
        //获取连接
        Connection connection = RabbitMqUtils.getConnection();
        //获取通道对象
        Channel channel = connection.createChannel();

        //通过通道声明队列
        channel.queueDeclare("work", true, false, false, null);

        for (int i = 0; i < 10; i++) {
            //生产消息
            channel.basicPublish("", "work", null, (i+"hello work quene").getBytes());
        }

        //关闭资源
        RabbitMqUtils.closeConnection(channel, connection);


    }
  1. 开发消费者-1
    public static void main(String[] args) throws IOException {
        //获取连接
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();

        channel.queueDeclare("work", true, false, false, null);

        channel.basicConsume("work", true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者-1:" + new String(body));
            }
        });
    }
  1. 开发消费者-2
    public static void main(String[] args) throws IOException {
        //获取连接
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();

        channel.queueDeclare("work", true, false, false, null);

        channel.basicConsume("work", true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者-2:" + new String(body));
            }
        });
    }
  1. 测试结果
    结果一
    结果二

总结:默认情况下,RabbitNQ将按顺序将每个消息发送给下一个使用者。平均而言,每个消费者都会收到相同数量的消息。这种分发消息的方式称为循环。

3.4.1、消息确认机制和能者多劳的实现

public class Customer1 {
    public static void main(String[] args) throws IOException {
        //获取连接
        Connection connection = RabbitMqUtils.getConnection();
        final Channel channel = connection.createChannel();
        //每一次只消费一个消息
        channel.basicQos(1);

        channel.queueDeclare("work", true, false, false, null);
        //参数1:队列名称,参数2:消息自动确认 true 消费者自动向rabbitmq确认消息消费 false 不会自动确认消息(即使被消费了但是队列中没被消费)
        channel.basicConsume("work", false, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("消费者-1:" + new String(body));
                //手动确认  参数1:手动确认消息标识    参数2:false每次确认一个
                //参数1:确认队列中那个具体消息,参数2:是否开启多个消息同时确定
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        });
    }
}
public class Customer2 {
    public static void main(String[] args) throws IOException {
        //获取连接
        Connection connection = RabbitMqUtils.getConnection();
        final Channel channel = connection.createChannel();
        channel.basicQos(1);
        channel.queueDeclare("work", true, false, false, null);

        channel.basicConsume("work", false, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者-2:" + new String(body));
                //手动确认  参数1:手动确认消息标识    参数2:false每次确认一个
                channel.basicAck(envelope.getDeliveryTag(), false);
            }
        });
    }
}

结果一
结果二

3.5、第三种模式(fanout)

fanout扇出也称广播
图解

在广播模式下,消息发送流程是这样的:
可以有多个消费者
每个消费者有自己的queue (队列)
每个队列都要绑定到Exchange (交换机)
生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
交换机把消息发送给绑定过的所有队列
队列的消费者都能拿到消息。实现一条消息被多个消费者消费

  1. 开发生产者
public class Provider {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();
        //将通道声名指定交换机    //参数1:交换机名称,参数2:交换机类型   fannout 广播类型
        channel.exchangeDeclare("logs","fanout");

        //发送消息,交换机名称,路由key此时没任何意义,持久化特性
        channel.basicPublish("logs","",null,"fanout type message".getBytes());

        RabbitMqUtils.closeConnection(channel,connection);
    }
}
  1. 消费者1、2、3
public class Customer1 {
    public static void main(String[] args) throws IOException {
        //获取链接对象
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();

        //通道绑定交换机
        channel.exchangeDeclare("logs", "fanout");

        //临时队列
        String queueName = channel.queueDeclare().getQueue();

        //绑定交换机和队列
        channel.queueBind(queueName, "logs", "");

        //消费信息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:" + new String(body));
            }
        });
    }
}

效果截图

3.6、第四种模式(Routing)

3.6.1、Routing之订阅模型-Direct(直连)

在Fanout模式中,一条消息,会被所有订阅的队列都消费。但是,在某些场景下,我们希望不同的消息被不同的队列消费。这时就要用到Direct类型的Exchange。

在Direct模型下:

  • 队列与交换机的绑定,不能是任意绑定了,而是要指定一个RoutingKey(路由key)
  • 消息的发送方在向Exchange发送消息时,也必须指定消息的 RoutingKey 。
  • Exchange不再把消息交给每一个绑定的队列,而是根据消息的Routing Key进行判断,只有队列的Routing key与消息的Routing key完全一致,才会接收到消息
    流程
    图解
    图解
  • P:生产者,向Exchange发送消息,发送消息时,会指定一个routing key。
  • X: Exchange (交换机),接收生产者的消息,然后把消息递交给与routing key完全匹配的队列
  • c1∶消费者,其所在队列指定了需要routing key 为error的消息
  • C2∶消费者,其所在队列指定了需要routing key为info、error、warning 的消息
  1. 开发生产者
public class Provider {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();
        String exchangeName = "logs_direct";
        //通过通道声名交换机 参数1:交换机名称   参数2:direct  路由模式
        channel.exchangeDeclare(exchangeName, "direct");
        //发送信息
        String routingkey = "error";
        channel.basicPublish(exchangeName, routingkey, null, ("这是direct模型发布的基于route key:[" + routingkey + "]").getBytes());
        //关闭资源
        RabbitMqUtils.closeConnection(channel, connection);
    }
}
  1. 消费者1
public class Customer1 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();

        String exchangeName = "logs_direct";

        //通道声明交换机以及交换的类型
        channel.exchangeDeclare(exchangeName, "direct");

        //创建一个临时队列
        String queueName = channel.queueDeclare().getQueue();

        //基于route key绑定队列和交换机,队列的名字,交换机,路由key
        channel.queueBind(queueName, exchangeName, "error");

        //获取消费的消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:" + new String(body));
            }
        });
    }
}
  1. 消费者2
public class Customer2 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();

        String exchangeName="logs_direct";

        //通道声明交换机以及交换的类型
        channel.exchangeDeclare(exchangeName, "direct");

        //创建一个临时队列
        String queueName = channel.queueDeclare().getQueue();

        //基于route key绑定队列和交换机,队列的名字,交换机,路由key
        channel.queueBind(queueName, exchangeName, "info");
        channel.queueBind(queueName, exchangeName, "error");
        channel.queueBind(queueName, exchangeName, "warning");

        //获取消费的消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel) {
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者2:" + new String(body));
            }
        });
    }
}

结果截图
结果
结果

3.7、第五种模式(Topic)

Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key的时候使用通配符!这种模型Routingkey一般都是由一个或多个单词组成,多个单词之间以""分割,例如: item.insert

图解

#统配符
	* (star) can substitute for exactly one word.匹配不多不少恰好1个词
	# (hash) can substitute for zero or more words.匹配一个或多个词
#如:
	audit.#		匹配audit.irs.corporate或者audit.irs等
	audit.		只能匹配audit.irs
  1. 生产者
public class Provider {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();
        //声明交换机以及交换机类型 topic
        channel.exchangeDeclare("topics","topic");
        //发布消息
        String routekey ="user";
        channel.basicPublish("topics",routekey,null,("这里是topic动态路由模型,routekey:["+routekey+"]").getBytes());

        //关闭资源
        RabbitMqUtils.closeConnection(channel,connection);
    }
}
  1. 消费者1
public class Customer1 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();

        //声明交换机以及类型
        channel.exchangeDeclare("topics","topic");
        //创建一个临时队列
        String queue = channel.queueDeclare().getQueue();
        //绑定队列和交换机,动态通配符形式route key
        channel.queueBind(queue,"topics","*.user.*");

        //消费消息
        channel.basicConsume(queue,true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:"+new String(body));
            }
        });
    }
}
  1. 消费者2
public class Customer2 {
    public static void main(String[] args) throws IOException {
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = connection.createChannel();

        //声明交换机以及类型
        channel.exchangeDeclare("topics","topic");
        //创建一个临时队列
        String queue = channel.queueDeclare().getQueue();
        //绑定队列和交换机,动态通配符形式route key
        channel.queueBind(queue,"topics","#.user.#");

        //消费消息
        channel.basicConsume(queue,true,new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                System.out.println("消费者1:"+new String(body));
            }
        });
    }
}

结果截图
结果截图

4、SpringBoot整合RabbitMQ

导入依赖

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>

配置文件

spring.application.name=rabbitmq-springboot
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=ems
spring.rabbitmq.password=ems
spring.rabbitmq.virtual-host=/ems

4.1、第一种HelloWord

RabbitTemplate 用来简化操作RabbitMQ,使用的时候直接在项目中注入即可

@Component//持久化,非独占,不是自动删除队列
@RabbitListener(queuesToDeclare = @Queue(value = "hello"))
public class HelloCustomer {

    //代表从队列中取出消息的回调方法
    @RabbitHandler
    public void receivel(String message) {
        System.out.println("message=" + message);
    }
}

测试

@SpringBootTest
class RabbitmqSpringbootApplicationTests {

	//注入rabbitTemplate
	@Autowired
	private RabbitTemplate rabbitTemplate;

	//hello world
	@Test
	void contextLoads() {
		//队列的名称,发送的消息
		rabbitTemplate.convertAndSend("hello","hello world");
	}
}

4.2、第二种Work

生产者

@SpringBootTest
class RabbitmqSpringbootApplicationTests {

    //注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //work,公平分配
    @Test
    public void testWork() {
		for (int i = 0; i < 10; i++) {
			rabbitTemplate.convertAndSend("work", "work模型");
		}
    }

}

消费者

@Component
public class WorkCustomer {
    @RabbitListener(queuesToDeclare = @Queue("work"))//可以加载类上和方法上,直接加载方法上,这个方法会处理当前rabbitlistener所监听的队列
    public void receivel(String message){
        System.out.println("message1 ="+message);
    }

    @RabbitListener(queuesToDeclare = @Queue("work"))
    public void receive2(String message){
        System.out.println("message2 ="+message);
    }
}

说明:默认在Spring AMOP实现中Work这种方式就是公平调度,如果需要实现能者多劳需要额外配置

4.3、第三种Publish/Subscribe

生产者发送的消息,只能发送到交换机,交换机来决定要发给哪个队列,生产者无法决定。
交换机把消息发送给绑定过的所有队列
生产者

@SpringBootTest
class RabbitmqSpringbootApplicationTests {

    //注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //fanout 广播
    @Test
    public void testFanout(){
        //交换机名字,路由key没关系
        rabbitTemplate.convertAndSend("logs","","Fanout的模型发送的消息");
    }

}

消费者

@Component
public class FanoutCustomer {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,//创建临时队列
                    exchange = @Exchange(value = "logs", type = "fanout")//绑定的交换机
            )
    })
    public void receive1(String message) {
        //先创建一个临时队列绑定交换机
        System.out.println("message1 =" + message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,//创建临时队列
                    exchange = @Exchange(value = "logs", type = "fanout")//绑定的交换机
            )
    })
    public void receive2(String message) {
        //先创建一个临时队列绑定交换机
        System.out.println("message2 =" + message);
    }
}

4.4、第四种Route

生产者

@SpringBootTest
class RabbitmqSpringbootApplicationTests {

    //注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //route路由模式
    @Test
    public void testRoute(){
        //交换机名字,路由的key
        rabbitTemplate.convertAndSend("directs","info","发送info的key的路由信息");
    }
}

消费者

@Component
public class RouteCustomer {
    /**
     * 先创建一个临时队列绑定交换机
     * @param message
     */
    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,//创建临时队列
                    exchange = @Exchange(value = "directs", type = "direct"),//自定义交换机名称和类型,类型默认direct
                    key = {"info", "error", "warn"}
            )
    })
    public void receive1(String message) {
        System.out.println("message1 =" + message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,//创建临时队列
                    exchange = @Exchange(value = "directs", type = "direct"),//自定义交换机名称和类型,类型默认direct
                    key = {"error",}
            )
    })
    public void receive2(String message) {
        System.out.println("message2 =" + message);
    }
}

效果图
效果图

4.5、第五种Route

生产者

@SpringBootTest
class RabbitmqSpringbootApplicationTests {

    //注入rabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //topic 动态路由    订阅模式
    @Test
    public void testTopic(){
        //交换机名字,路由的key
        rabbitTemplate.convertAndSend("topics","user.save","user.save 路由消息");
        rabbitTemplate.convertAndSend("topics","user.save.delete","user.save.delete 路由消息");
        rabbitTemplate.convertAndSend("topics","order.save","order.save 路由消息");
        rabbitTemplate.convertAndSend("topics","order.save.delete","order.save.delete 路由消息");
    }
}

消费者

@Component
public class TopicCustomer {

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(type = "topic",name = "topics"),
                    key = {"user.save","user.*"}
            )
    })
    public void receive1(String message){
        System.out.println("message1 =" + message);
    }

    @RabbitListener(bindings = {
            @QueueBinding(
                    value = @Queue,
                    exchange = @Exchange(type = "topic",name = "topics"),
                    key = {"order.#","produce.#","user.*"}
            )
    })
    public void receive2(String message){
        System.out.println("message2 =" + message);
    }
}

效果图
效果图

5、MQ的应用场景

5.1、异步处理

场景

5.2、应用解耦

应用解耦

5.3、流量削峰

峰值

6、集群架构

6.1、普通集群

默i认情况下:RabitK0代理操作所需的所有数据/状态都将跨所有节点复制。这方面的一个例外是消息队列,默认情况下,消息队列位于一个节点上,尽管它们可以从所有节点看到和访问

架构图(有点像主备架构)
架构图

核心解决问题:当集群中某一时刻master节点宕机,可以对Quene中信息,进行备份

集群搭建

# 1.集群规划
node1 : 10.15.0.3	mq1		master	主节点
node2 : 10.15.0.4	mq2		repl1	副本节点
node3 : 10.15.8.5	mq3		repl2	副本节点

# 2.克隆三台机器主机名和ip映射(三台机器都要)
vim /etc/hosts加入:
		10.15.8.3 mq1
		18.15.0.4 mq2
		10.15.0.5 mq3
node1 : vim letc/hostname 加入:mq1
node2 : vim /etc/hostname 加入:mq2
node3 : vim /etc/hostname 加入:mq3

# 3.三个机器安装rabbitmq,并同步cookie文件,在node1上执行:
scp /var/lib/rabbitmq/.erlang.cookie root@mq2 : / var/lib/rabbitmq/
scp /var/lib/rabbitmq/.erlang.cookie root@mq3 : / var/lib/rabbitmq/

# 4.后台启动rabbitmq所有节点执行如下命令,启动成功访问管理界面:
rabbitmq-server -detached

# 5.在node2和node3执行加入集群命令:
1.关闭		rabbitmqctl stop_app
2.加入集群	rabbitmqctl join_cluster rabbitemq1
3.启动服务	rabbitmqctl start_app

# 6.查看集群状态,任意节点执行:
rabbitmqctl cluster_status

# 7.如果出现如下显示,集群搭建成功:
Cluster status of node rabbit@mq3 ...
[ {nodes , [ idisc , [ rabbit@mq1 , rabbit@mq2 , rabbit@mq3] 》]}.
frunning_nodes , [ rabbit@mq1 , rabbitemq2 , rabbit@mq3 ]},
{cluster_name , <<"rabbit@mq1">>},
{partitions, [ ]},
{alarms, [ {rabbit@mq1 , []} , { rabbit@mq2,[ ]} , {rabbit@mq3,[]}H]


安装rabbitmq

(修改rabbitmq.config61行取消对{handshake_timeout,10000}}的注释,去掉行结尾逗号)
# 7.执行如下命令,启动rabbitmq中的插件管理
rabbitmq-plugins enable rabbitmq_management
#8.启动RabbitMQ的服务
systemctl start 	rabbitmq-server
systemctl restart 	rabbitmq-server
systemctl stop 		rabbitmq-server

安装包
安装包
集群的搭建

6.2、镜像集群(用的多)

解决了高可用,把主队列信息同步到不同的rabbit服务器

镝像队刭列机制就是将队列在三个节点之间设置主从关系,消息会在三个节点之间进行自动同步,且如果其中一个节点不可用,并不会导致消息丢失或服务不可用的情况,提升NO集群的整体高可用性。

在这里插入图片描述

集群架构

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

和烨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值