RabbitMq

消息队列

在这里插入图片描述

在这里插入图片描述

1.pom引入依赖

引入依赖后:容器中自动配置RabbitTemplate、AmqpAdmin、CachingConnectionFactory、RabbitMessagingTemplate

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

2.启动类添加@EnableRabbit

3.配置文件

# RabbitMQ配置
spring.rabbitmq.host=192.168.56.10
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin
# 虚拟主机配置
spring.rabbitmq.virtual-host=/
server.port=9999

4.收发消息测试

大致流程,有一个队列绑定到一个直连交换机上,同时赋予一个路由键 routing key 。
然后当一个消息携带着路由值为X,这个消息通过生产者发送给交换机时,交换机就会根据这个路由值X去寻找绑定值也是X的队列。

1.Direct Exchange

直连型交换机,根据消息携带的路由键将消息投递给对应队列。

1.配置
/**
 *@author: lzp
 *@create: 2022-11-09 20:14:43
 *@description: rabbitmq配置类
 */
@Configuration
public class RabbitConfig {

    //队列 起名:TestDirectQueue
    @Bean
    public Queue TestDirectQueue() {
        // durable:是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效
        // exclusive:默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable
        // autoDelete:是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。
        //   return new Queue("TestDirectQueue",true,true,false);

        //一般设置一下队列的持久化就好,其余两个就是默认false
        return new Queue("TestDirectQueue",true);
    }


    //Direct交换机 起名:TestDirectExchange
    @Bean
    DirectExchange TestDirectExchange() {
        //  return new DirectExchange("TestDirectExchange",true,true);
        return new DirectExchange("TestDirectExchange",true,false);
    }

    //绑定  将队列和交换机绑定, 并设置用于匹配键:TestDirectRouting
    @Bean
    Binding bindingDirect() {
        return BindingBuilder.bind(TestDirectQueue()).to(TestDirectExchange()).with("TestDirectRouting");
    }

    @Bean
    DirectExchange lonelyDirectExchange() {
        return new DirectExchange("lonelyDirectExchange");
    }
}
2.发送
    @GetMapping("/sendDirectMessage")
    public String sendDirectMessage() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "test message, hello!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        //将消息携带绑定键值:TestDirectRouting 发送到交换机TestDirectExchange
        rabbitTemplate.convertAndSend("TestDirectExchange", "TestDirectRouting", map);
        return "ok";
    }
3.接收
@org.springframework.amqp.rabbit.annotation.RabbitListener(queues =  "TestDirectQueue")
@Component
public class RabbitListener {
    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("DirectReceiver消费者收到消息  : " + testMessage.toString());
    }
}
4.效果

在这里插入图片描述
配置多台监听绑定到同一个直连交互的同一个队列,那么会轮询收到消息,轮询的方式对消息进行消费,而且不存在重复消费。

2.Fanout Exchange

扇型交换机,这个交换机没有路由键概念,就算你绑了路由键也是无视的。 这个交换机在接收到消息后,会直接转发到绑定到它上面的所有队列。

1.配置
/**
 * @Author: lzp
 * @Description:
 * @Date: 2022/11/9 20:57
 * @Version: 1.0
 * @Modified By:
 */
@Configuration
public class FanoutRabbitConfig {

    /**
     *  创建三个队列 :fanout.A   fanout.B  fanout.C
     *  将三个队列都绑定在交换机 fanoutExchange 上
     *  因为是扇型交换机, 路由键无需配置,配置也不起作用
     */


    @Bean
    public Queue queueA() {
        return new Queue("fanout.A",true);
    }

    @Bean
    public Queue queueB() {
        return new Queue("fanout.B",true);
    }

    @Bean
    public Queue queueC() {
        return new Queue("fanout.C",true);
    }

    @Bean
    FanoutExchange fanoutExchange() {
        return new FanoutExchange("fanoutExchange");
    }

    @Bean
    Binding bindingExchangeA() {
        return BindingBuilder.bind(queueA()).to(fanoutExchange());
    }

    @Bean
    Binding bindingExchangeB() {
        return BindingBuilder.bind(queueB()).to(fanoutExchange());
    }

    @Bean
    Binding bindingExchangeC() {
        return BindingBuilder.bind(queueC()).to(fanoutExchange());
    }

}
2.发送
    @GetMapping("/sendFanoutMessage")
    public String sendFanoutMessage() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "message: testFanoutMessage ";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> map = new HashMap<>();
        map.put("messageId", messageId);
        map.put("messageData", messageData);
        map.put("createTime", createTime);
        rabbitTemplate.convertAndSend("fanoutExchange", null, map);
        return "ok";
    }
3.接收
@Component
@RabbitListener(queues = "fanout.A")
public class FanoutReceiverA {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("FanoutReceiverA消费者收到消息  : " +testMessage.toString());
    }
}
@Component
@RabbitListener(queues = "fanout.B")
public class FanoutReceiverB {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("FanoutReceiverB消费者收到消息  : " +testMessage.toString());
    }

}
@Component
@RabbitListener(queues = "fanout.C")
public class FanoutReceiverC {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("FanoutReceiverC消费者收到消息  : " +testMessage.toString());
    }

}
4.效果

ABC都能收到
在这里插入图片描述
只要发送到 fanoutExchange 这个扇型交换机的消息, 三个队列都绑定这个交换机,所以三个消息接收类都监听到了这条消息

3.Topic Exchange

主题交换机,这个交换机其实跟直连交换机流程差不多,但是它的特点就是在它的路由键和绑定键之间是有规则的。
* (星号) 用来表示一个单词 (必须出现的)
# (井号) 用来表示任意数量(零个或多个)单词
通配的绑定键是跟队列进行绑定的,举个小例子
队列Q1 绑定键为 .TT. 队列Q2绑定键为 TT.#
如果一条消息携带的路由键为 A.TT.B,那么队列Q1将会收到;
如果一条消息携带的路由键为TT.AA.BB,那么队列Q2将会收到;

1.配置
/**
 *@author: lzp
 *@create: 2022-11-09 20:33:31
 *@description: 主题交换机
 */
@Configuration
public class TopicRabbitConfig {

    //绑定键
    public final static String man = "topic.man";
    public final static String woman = "topic.woman";

    @Bean
    public Queue firstQueue() {
        return new Queue(TopicRabbitConfig.man,true);
    }

    @Bean
    public Queue secondQueue() {
        return new Queue(TopicRabbitConfig.woman,true);
    }

    /**
     *@Author: lzp
     *@Description: 主题交换机
     *@Date: 2022/11/9 20:35
     *@Params []
     *@return org.springframework.amqp.core.TopicExchange
     **/
    @Bean
    TopicExchange exchange() {
        return new TopicExchange("topicExchange");
    }


    //将firstQueue和topicExchange绑定,而且绑定的键值为topic.man
    //这样只要是消息携带的路由键是topic.man,才会分发到该队列
    @Bean
    Binding bindingExchangeMessage() {
        return BindingBuilder.bind(firstQueue()).to(exchange()).with(man);
    }

    //将secondQueue和topicExchange绑定,而且绑定的键值为用上通配路由键规则topic.#
    // 这样只要是消息携带的路由键是以topic.开头,都会分发到该队列
    @Bean
    Binding bindingExchangeMessage2() {
        return BindingBuilder.bind(secondQueue()).to(exchange()).with("topic.#");
    }

}
2.发送
    @GetMapping("/sendTopicMessage1")
    public String sendTopicMessage1() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "message: M A N ";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> manMap = new HashMap<>();
        manMap.put("messageId", messageId);
        manMap.put("messageData", messageData);
        manMap.put("createTime", createTime);
        rabbitTemplate.convertAndSend("topicExchange", "topic.man", manMap);
        return "ok";
    }

    @GetMapping("/sendTopicMessage2")
    public String sendTopicMessage2() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "message: woman is all ";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String, Object> womanMap = new HashMap<>();
        womanMap.put("messageId", messageId);
        womanMap.put("messageData", messageData);
        womanMap.put("createTime", createTime);
        rabbitTemplate.convertAndSend("topicExchange", "topic.woman", womanMap);
        return "ok";
    }
3.接收
/**
 *@author: lzp
 *@create: 2022-11-09 20:37:41
 *@description: man
 */
@Component
@RabbitListener(queues = "topic.man")
public class TopicManReceiver {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("TopicManReceiver消费者收到消息  : " + testMessage.toString());
    }

}
/**
 * @Author: lzp
 * @Description:
 * @Date: 2022/11/9 20:52
 * @Version: 1.0
 * @Modified By:
 */
@Component
@RabbitListener(queues = "topic.woman")
public class TopicTotalReceiver {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("TopicTotalReceiver消费者收到消息  : " + testMessage.toString());
    }

}

此时发送消息1 两个接收者都能收到
发送消息2 只有第二个监听者能收到(第二个绑定的路由键是topic.#,只要是topic开头的就可以)

4.Header Exchange 头交换机

5.Default Exchange 默认交换机

6.Dead Letter Exchange 死信交换机

死信队列和死信交换机和普通的队列一样,作用是,当普通队列中的消息没有被正常消费的时候,消息就会进到正常业务队列绑定的死信交换机和死信队列中去。保证消息不丢失。
进入死信队列的条件有三种:
1.消息被否定确认,使用 channel.basicNack 或 channel.basicReject ,并且此时requeue 属性被设置为false。
2.消息在队列的存活时间超过设置的TTL时间。
3.消息队列的消息数量已经超过最大队列长度。

1.配置
@Configuration
public class DeadRabbitConfig {

    public static final String BUSINESS_EXCHANGE_NAME = "dead.letter.demo.simple.business.exchange";
    public static final String BUSINESS_QUEUEA_NAME = "dead.letter.demo.simple.business.queuea";
    public static final String BUSINESS_QUEUEB_NAME = "dead.letter.demo.simple.business.queueb";
    public static final String DEAD_LETTER_EXCHANGE = "dead.letter.demo.simple.deadletter.exchange";
    public static final String DEAD_LETTER_QUEUEA_ROUTING_KEY = "dead.letter.demo.simple.deadletter.queuea.routingkey";
    public static final String DEAD_LETTER_QUEUEB_ROUTING_KEY = "dead.letter.demo.simple.deadletter.queueb.routingkey";
    public static final String DEAD_LETTER_QUEUEA_NAME = "dead.letter.demo.simple.deadletter.queuea";
    public static final String DEAD_LETTER_QUEUEB_NAME = "dead.letter.demo.simple.deadletter.queueb";

    // 声明业务Exchange
    @Bean("businessExchange")
    public FanoutExchange businessExchange(){
        return new FanoutExchange(BUSINESS_EXCHANGE_NAME);
    }

    // 声明死信Exchange
    @Bean("deadLetterExchange")
    public DirectExchange deadLetterExchange(){
        return new DirectExchange(DEAD_LETTER_EXCHANGE);
    }

    // 声明业务队列A
    @Bean("businessQueueA")
    public Queue businessQueueA(){
        Map<String, Object> args = new HashMap<>(3);
//       x-dead-letter-exchange    这里声明当前队列绑定的死信交换机
        args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
//       x-dead-letter-routing-key  这里声明当前队列的死信路由key
        args.put("x-dead-letter-routing-key", DEAD_LETTER_QUEUEA_ROUTING_KEY);
        // 消息过期时间 60s
        args.put("x-message-ttl", 10000);
        return QueueBuilder.durable(BUSINESS_QUEUEA_NAME).withArguments(args).build();
    }

    // 声明业务队列B
    @Bean("businessQueueB")
    public Queue businessQueueB(){
        Map<String, Object> args = new HashMap<>(3);
//       x-dead-letter-exchange    这里声明当前队列绑定的死信交换机
        args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE);
//       x-dead-letter-routing-key  这里声明当前队列的死信路由key
        args.put("x-dead-letter-routing-key", DEAD_LETTER_QUEUEB_ROUTING_KEY);
        // 消息过期时间 60s
        args.put("x-message-ttl", 60000);
        return QueueBuilder.durable(BUSINESS_QUEUEB_NAME).withArguments(args).build();
    }

    // 声明死信队列A
    @Bean("deadLetterQueueA")
    public Queue deadLetterQueueA(){
        return new Queue(DEAD_LETTER_QUEUEA_NAME);
    }

    // 声明死信队列B
    @Bean("deadLetterQueueB")
    public Queue deadLetterQueueB(){
        return new Queue(DEAD_LETTER_QUEUEB_NAME);
    }

    // 声明业务队列A绑定关系
    @Bean
    public Binding businessBindingA(@Qualifier("businessQueueA") Queue queue,
                                    @Qualifier("businessExchange") FanoutExchange exchange){
        return BindingBuilder.bind(queue).to(exchange);
    }

    // 声明业务队列B绑定关系
    @Bean
    public Binding businessBindingB(@Qualifier("businessQueueB") Queue queue,
                                    @Qualifier("businessExchange") FanoutExchange exchange){
        return BindingBuilder.bind(queue).to(exchange);
    }

    // 声明死信队列A绑定关系
    @Bean
    public Binding deadLetterBindingA(@Qualifier("deadLetterQueueA") Queue queue,
                                      @Qualifier("deadLetterExchange") DirectExchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with(DEAD_LETTER_QUEUEA_ROUTING_KEY);
    }

    // 声明死信队列B绑定关系
    @Bean
    public Binding deadLetterBindingB(@Qualifier("deadLetterQueueB") Queue queue,
                                      @Qualifier("deadLetterExchange") DirectExchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with(DEAD_LETTER_QUEUEB_ROUTING_KEY);
    }
}
2.发送
    /**
     * 测试死信队列
     */

    @GetMapping("/sendDeadMessage")
    public String sendDeadMessage(){
    //发送消息,如果发送的消息是个对象,会使用序列化机制,将对象写出去,对象必须实现Serializable接口
        User user = new User();
        user.setAge(18);
        user.setName("张三");
        rabbitTemplate.convertAndSend(BUSINESS_EXCHANGE_NAME, null, user,
                //消息的唯一id 在后面的确认回调可以用到。
                new CorrelationData(UUID.randomUUID().toString()));
        return "ok";
    }
3.接收

为了测试效果 先不接收

4.效果

发送消息后,看控制台。消息会先进到正常队列中去
在这里插入图片描述
等消息过期后,消息会进到死信队列
在这里插入图片描述

发送消息

    //发送消息使用RabbitTemplate
    @Autowired
    RabbitTemplate rabbitTemplate;

    @GetMapping("/sendMq")
    public String sendMessageTest() {
        for (int i = 0; i < 10; i++) {
            if(i%2==0){
                OrderReturnReasonEntity reasonEntity = new OrderReturnReasonEntity();
                reasonEntity.setId(1L);
                reasonEntity.setCreateTime(new Date());
                reasonEntity.setName("哈哈"+i);
                String msg = "Hello World";
                //1、发送消息,如果发送的消息是个对象,会使用序列化机制,将对象写出去,对象必须实现Serializable接口
                //2、发送的对象类型的消息,可以是一个json
                rabbitTemplate.convertAndSend(
                        "hello-java-exchange",//交换机名字
                        "hello.java", //路由键,决定交换机把消息传给哪个队列
                        reasonEntity,//发送的消息为对象
                        new CorrelationData(UUID.randomUUID().toString()));//消息的唯一id 在后面的确认回调可以用到。
            }else{
                OrderEntity orderEntity = new OrderEntity();
                orderEntity.setOrderSn(UUID.randomUUID().toString());
                //1、发送消息,如果发送的消息是个对象,会使用序列化机制,将对象写出去,对象必须实现Serializable接口
                //2、发送的对象类型的消息,可以是一个json
                rabbitTemplate.convertAndSend(
                        "hello-java-exchange",
                        "hello.java",
                        orderEntity,
                        new CorrelationData(UUID.randomUUID().toString()));
            }
        }
        return  "ok";
    }

发送的消息类型为对象时,需要将序列化后的数据转为json

@Configuration
public class MyRabbitConfig {
    @Bean
    public MessageConverter messageConverter(){
        return  new Jackson2JsonMessageConverter();
    }
}

接收消息,监听消息

    /**
     * channel:当前传输数据的通道
     * queue:可以很多人都来监听,只要收到消息,队列删除消息,而且只能有一个收到此消息
     * (1)服务启动多个,同一个消息只能有一个服务接收到
     * (2)只有一个消息完全处理完,方法运行结束,才能接收到下一个消息
     */
    //参数类型可以是message 实体类 channel
    @RabbitHandler
    public void revieveMessage(Message message,
                               OrderReturnReasonEntity content,
                               Channel channel) {
        //拿到主体内容
        byte[] body = message.getBody();
        //拿到的消息头属性信息
        MessageProperties messageProperties = message.getMessageProperties();
        System.out.println("接受到的消息...内容" + message + "===内容:" + content);
    }
    @RabbitHandler
    public void revieveMessage(OrderEntity orderEntity) {

        System.out.println("接受到的消息...内容"  + orderEntity);
    }

@RabbitHandler 可以接收特定对象 只能用在方法上
@RabbitListener(queues = {“hello-java-queue”}) 接收指定队列的消息 用在类上

5.消息确认机制-可靠抵达

1.服务端确认

两种确认
一种是消息到rabbitmq服务器就产生回调,告诉本地服务器他收到消息了,
另一种是消息从交换机到队列的监听,如果消息没有从交换机到队列(比如路由键不对),就会产生回调,告诉本地服务器哪个消息未到队列,
后期可以在发送消息的时候,同时在数据库持久化保存一份,并设置rabbit服务器是否正确收到消息这一字段,通过回调方法设置该字段的值,后期定期检查数据库,对未正确发送的消息进行处理
配置文件:

#服务端消息确认
#确认消息已发送到交换机(Exchange)
spring.rabbitmq.publisher-confirm-type=correlated
#确认消息已发送到队列(Queue)
spring.rabbitmq.publisher-returns=true
spring.rabbitmq.template.mandatory=true

配置类

@Configuration
public class ConfirmConfig {

    /**
     * 消息确认机制
     * @param connectionFactory
     * @return
     */
    @Bean
    public RabbitTemplate createRabbitTemplate(ConnectionFactory connectionFactory){

        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        //这里一定要设置 不然发送对象类型的消息会报错
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
        rabbitTemplate.setConnectionFactory(connectionFactory);
        //到交换机回调 到不到交换机都会回调
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean b, String s) {
                System.out.println("123");
            }
        });
        //到队列回调 只有在消息未到队列时才会回调
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                System.out.println(returnedMessage);
            }
        });
        return rabbitTemplate;
    }
}

2.消费端确认

保证每个消息都被正确消费,此时才可以broker删除这个消息
所以一定要手动确认

(1)默认是自动确认的,只要消息接收到,客户端会自动确认,服务端就会移除消息

配置文件

#手动ack消息,不使用默认的消费端确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual

手动确认模式,只要我们没有明确告诉MQ,货物被签收了,没有ack,消息就一直是unacked状态,即使consumer宕机,消息也不会丢失,消息会重新变为ready状态,再有新的consumer连接,可以继续接收消息。
(2)channel.basicAck(deleverTag,false)签收,业务正常完成就应该签收 false:不是批量接收模式
(3)channel.basicNack(deleverTag,false,true)拒签 业务失败,拒签 false:不是批量接收模式,true:拒签后让消息重新回到queue
delivertag:
long deliveryTag = message.getMessageProperties().getDeliveryTag();//接收消息的自增长编号,1.2.3.4.5
手动确认最好不要继续让消息重新回到队列,这样会形成死循环,消息一直不能被消费,一直回到队列。有两种处理方式:

1.死信队列

配置的方法就是在声明队列的时候,添加参数 x-dead-letter-exchange 及 x-dead-letter-routing-key,其实就是在消费失败时,将消息使用该 exchange 及 routing key 发送至指定队列。
当你在消费消息时,如果队列里的消息出现以下情况:
1.消息被否定确认,使用 channel.basicNack 或 channel.basicReject ,并且此时requeue 属性被设置为false。
2.消息在队列的存活时间超过设置的TTL时间。
3.消息队列的消息数量已经超过最大队列长度。
这时消息会进入死信队列。我们可以不监听死信队列,定期到rabbit mq服务器去查看,把进入死信队列的消息再发一遍。或者监听,进一步处理数据(保存到数据库)

2.catch中处理

catch中将消息保存到数据库,然后手动决绝这条消息,requeue指定为false将消息丢弃。然后定期检查数据库,进行消息重发。

6.问题解决

1.消息丢失

消息发送出去,由于网络问题没有抵达服务器。
做好容错方法(try-catch),发送消息可能会网络失败,失败后要有重试机制,可记录到数据库,采用定期扫描重发的方式,每个消息状态是否都被服务器收到都应该记录。
做好定期重发,如果消息没有发送成功,定期去数据库扫描未成功的消息进行重发。
消息抵达Broker,Broker要将消息写入磁盘(持久化)才算成功。此时Broker尚未持久化完成,宕机。
publisher也必须加入确认回调机制,确认成功的消息,修改数据库消息状态。
自动ACK的状态下。消费者收到消息,但没来得及消息然后宕机
一定开启手动ACK,消费成功才移除,失败或者没来得及处理就noAck,对消息进行数据库保存或者使用死信队列,定期检查进行消息重发。
在这里插入图片描述

2.消息重复

消息消费成功,事务已经提交,ack时,机器宕机。导致没有ack成功,Broker的消息重新由unack变为ready,并发送给其他消费者
消息消费失败,由于重试机制,自动又将消息发送出去
成功消费,ack时宕机,消息由unack变为ready,Broker又重新发送
消费者的业务消费接口应该设计为幂等性的。比如扣库存有 工作单的状态标志
使用防重表(redis/mysql),发送消息每一个都有业务的唯 一标识,处理过就不用处理
rabbitMQ的每一个消息都有redelivered字段,可以获取是否 是被重新投递过来的,而不是第一次投递过来的

3.消息积压

消费者宕机积压
消费者消费能力不足积压
发送者发送流量太大
上线更多的消费者,进行正常消费
上线专门的队列消费服务,将消息先批量取出来,记录数据库,离线慢慢处理

7.docker安装

1.拉取镜像

docker pull rabbitmq:management

2.创建文件夹

在这里插入图片描述

3.运行(账号密码admin 访问网页 服务器ip:15672)

docker run --privileged=true
-d -p 5672:5672 -p 15672:15672
–name rabbitmq
-v /lzp/rabbitmq/data:/var/lib/rabbitmq
–restart=always
-e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin
rabbitmq:management

参考链接1
参考链接2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值