RabbitMQ基础(简单易懂)

1、MQ概念

MQ:消息队列,底层为先进先出数据结构的消息服务器;

MQ作用:实现两个系统中的数据传输,消息即为传输的数据。 

 - 系统间传输数据的传统方式

 - 系统间传输数据的队列方式

传统方式:同步,能够立刻拿到被调用接口处理后的数据;

消息队列(MQ):异步,效率高,无法拿到消费者处理后的数据

MQ的应用场景:系统解耦,流量消峰,数据分发

2、RabbitMQ工作原理

  • Producer(生产者):负责进行消息的发送
  • Consumer(消费者):负责从MQ中获取消息进行消费
  • Broker(代理):RabbitMQ的服务端
  • Exchange(交换机):不存储消息,只转发消息,把消息转发给指定队列
  • Queue(队列):负责存储消息

3、使用

(1)环境搭建

  • 使用docker拉取镜像,本次使用版本为3.8 
docker pull rabbitmq:3.8-management
  • 使用docker安装rabbitMQ容器,设置端口,挂载点等
docker run -d --name rabbit01 -e RABBITMQ_DEFAULT_USER=admin \
-e RABBITMQ_DEFAULT_PASS=admin \
-p 15672:15672 -p 5672:5672 \
--hostname rabbit01 --restart=always \
-v rabbit01_data:/var/lib/rabbitmq \
-v rabbit01_conf:/etc/rabbitmq \
rabbitmq:3.8-management
  • 使用ip和端口查看rabbitMQ的后台管理系统

(2)编写代码

2.1 简单队列模型的实现

 使用重点:注入RabbitTemplate发消息,给方法添加@RabbitListener(queues="simple_queue")注解收消息

  •  创建Maven工程,导入springboot与mq的启动项与springboot与junit的启动项
<!-- 指定父工程 -->
<parent>
  <artifactId>spring-boot-starter-parent</artifactId>
  <groupId>org.springframework.boot</groupId>
  <version>2.3.6.RELEASE</version>
</parent>

<dependencies>
  <!-- spring boot和rabbitmq整合的时候所需要的起步依赖 -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
  </dependency>

  <!-- spring boot和junit整合的起步依赖 -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
  </dependency>
</dependencies>
  • 创建producer(生产者)子模块,在子模块中创建Application启动器
@SpringBootApplication
public class RabbitmqProducerApplication {
    public static void main(String[] args) {
        SpringApplication.run(RabbitmqProducerApplication.class,args);
    }
}
  • 在yml文件中配置rabbitMQ的参数 
spring:
  rabbitmq:
    host: 192.168.126.137
    port: 5672
    username: admin
    password: admin
    virtual-host: /
  •  在producer模块中创建测试方法,注入rabbitTemplate依赖,调用其方法发送消息
@SpringBootTest
    public class Producer01 {

        @Autowired
        RabbitTemplate rabbitTemplate;

        //生产者1,测试简单模式
        @Test
        public void test01(){
            rabbitTemplate.convertAndSend("simple_queue","测试消息1");
        }
    }
  • 创建consumer(消费者)子模块;在其中创建Application启动器 
@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class,args);
    }
}
  • 配置参数 
spring:
  rabbitmq:
    host: 192.168.126.137
    port: 5672
    username: admin
    password: admin
    virtual-host: /
  • 在子模块中创建listener01包,并创建一个监听类,类上加@Component注解,创建方法并在方法上加@RabbitListener注解,方法中带参数Message,注解中带参数(queues=“simple_queue”)
@Component
public class Listen01 {
//    创建监听器用来消费消息队列中的消息
//    简单队列消费者
    @RabbitListener(queues = "simple_queue01")
    public void consumer01(Message message){
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("msg------>"+s);
    }
}

 2.2 工作队列模型的实现

 使用重点:降低生产速度,提高消费速度;注入RabbitTemplate发消息,给方法添加@RabbitListener(queues="simple_queue")注解收消息

  • 创建生产模块方法,使用循环发送多个消息 
//生产者2,测试工作模式
    @Test
    public void test02(){
        for (int i = 0; i < 10; i++) {
            rabbitTemplate.convertAndSend("simple_queue01","测试消息2"+i);
        }
    }
  •  在消费模块中再创建一个listener02包,并创建消费方法
@Component
public class Listen02 {
//    创建监听器用来消费消息队列中的消息
//    简单队列消费者
    @RabbitListener(queues = "simple_queue01")
    public void consumer01(Message message){
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("consumer-02------>"+s);
    }
}

2.3 发布订阅模型

使用重点:多了一个exchange(交换机)的角色,需要手动指定消息转发的队列;使用的交换机为Fanout交换机,自动将生产者的消息发送给所有与交换机绑定的队列;

Fanout交换机

特点:将消息转发给所有绑定的队列,创建方法为ExchangeBuilder,QueueBuilder,BindingBuilder

  • 在生产者中创建配置类
@Configuration
public class ProducerConfiguration {
//    创建交换机
    @Bean
    public Exchange fanoutExchange(){
         Exchange fanoutexchange = ExchangeBuilder.fanoutExchange("fanout_exchange")
                .durable(true).build();
        return fanoutexchange;
    }
//    创建队列01
    @Bean
    public Queue queue01(){
        Queue queue01 = QueueBuilder.durable("queue01").build();
        return queue01;
    }

//    创建队列02
    @Bean
    public Queue queue02(){
        Queue queue02 = QueueBuilder.durable("queue02").build();
        return queue02;
    }

//    创建绑定1
    @Bean
    public Binding binding01(){
        Binding binding01 = BindingBuilder.bind(queue01()).to(fanoutExchange()).with("").noargs();
        return binding01;
    }

//    创建绑定2
    @Bean
    public Binding binding02(){
        Binding binding02 = BindingBuilder.bind(queue02()).to(fanoutExchange()).with("").noargs();
        return binding02;
    }
}
  • 在消费者中创建两个监听类消费消息
@Component
public class Listen01 {
    @RabbitListener(queues = "queue01")
    public void consumer01(Message message){
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("consumer01---->"+s);
    }
}


@Component
public class Listen02 {
    @RabbitListener(queues = "queue02")
    public void consumer02(Message message){
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("consumer02---->"+s);
    }
}
  • 在消费者中创建测试方法给交换机发送消息
//生产者3,测试订阅模式
    @Test
    public void test03(){
        rabbitTemplate.convertAndSend("fanout_exchange","","你好fanout交换机!!");
    }

 2.4 路由模型

 重点:交换机将消息通过路由(字符串匹配)发送到响应队列

 Direct交换机

 特点:将消息转发给指定路由的队列

  •  在生产者模块中创建配置类
@Configuration
public class DirectConfigurarion {
//    创建交换机
    @Bean
    public Exchange directExchange(){
        Exchange directExchange = ExchangeBuilder.directExchange("direct_exchange").durable(true).build();
        return directExchange;
    }

//    创建队列03
    @Bean
    public Queue queue03(){
        Queue queue03 = QueueBuilder.durable("queue03").build();
        return queue03;
    }

//    创建队列04
    @Bean
    public Queue queue04(){
        Queue queue04 = QueueBuilder.durable("queue04").build();
        return queue04;
    }

//    创建绑定error
    @Bean
    public Binding binding03(){
        Binding binding03 = BindingBuilder.bind(queue03()).to(directExchange()).with("error").noargs();
        return binding03;
    }

//    创建绑定error
    @Bean
    public Binding binding04(){
        Binding binding04 = BindingBuilder.bind(queue04()).to(directExchange()).with("error").noargs();
        return binding04;
    }

//    创建绑定info
    @Bean
    public Binding binding05(){
        Binding binding04 = BindingBuilder.bind(queue04()).to(directExchange()).with("info").noargs();
        return binding04;
    }
}
  •  在消费者模块创建监听类
@Component
public class Listen03 {
    @RabbitListener(queues = "queue03")
    public void consumer03(Message message){
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("consumer03---->"+s);
    }
}
  •  在生产者中创建测试方法
//生产者4,测试路由模式
    @Test
    public void test04(){
        rabbitTemplate.convertAndSend("direct_exchange","error","测试error消息,同时发送给03和04");
        rabbitTemplate.convertAndSend("direct_exchange","info","测试info消息,只发送给04");
    }

 2.5 主题模型

重点:动态路由,在绑定时可以使用通配符,路由路径分为*和#

Topic交换机

特点:路径中通配符为#,可以匹配0个或多个词;路径中通配符为*,可以只能匹配1个词

  • 在生产模块中创建配置类
@Configuration
public class TopicConfiguration {

//    创建交换机
    @Bean
    public Exchange topicExchange(){
        Exchange topicExchange = ExchangeBuilder.topicExchange("topic_exchange").durable(true).build();
        return topicExchange;
    }

//    创建队列
    @Bean
    public Queue queue05(){
        Queue queue05 = QueueBuilder.durable("queue05").build();
        return queue05;
    }

//    创建队列
    @Bean
    public Queue queue06(){
        Queue queue06 = QueueBuilder.durable("queue06").build();
        return queue06;
    }

//    创建绑定05
    @Bean
    public Binding binding5(){
        Binding binding05 = BindingBuilder.bind(queue05())
                .to(topicExchange()).with("*.orange.*").noargs();
        return binding05;
    }

//    创建绑定06
    @Bean
    public Binding binding6(){
        Binding binding06 = BindingBuilder.bind(queue06())
                .to(topicExchange()).with("lazy.#").noargs();
        return binding06;
    }
}
  • 在消费模块中创建监听器
@Component
public class Listen05 {
    @RabbitListener(queues = "queue05")
    public void consumer05(Message message){
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("consumer05---->"+s);
    }
}

@Component
public class Listen06 {
    @RabbitListener(queues = "queue06")
    public void consumer06(Message message){
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("consumer06---->"+s);
    }
}
  • 在生产模块中创建测试方法
//生产者5,测试主题模式
    @Test
    public void test05(){
        rabbitTemplate.convertAndSend("topic_exchange","a.orange.b","测试*.orange.*匹配一个路径");
        rabbitTemplate.convertAndSend("topic_exchange","orange.a.b","测试*.orange.*匹配零个路径");
        rabbitTemplate.convertAndSend("topic_exchange","lazy.a","测试lazy.*匹配一个路径");
        rabbitTemplate.convertAndSend("topic_exchange","lazy.a.b","测试lazy.*匹配两个路径");
        rabbitTemplate.convertAndSend("topic_exchange","lazy","测试lazy.*匹配零个路径");
    }

4、注解方式创建配置

重点:在使用时常规操作较为繁琐,需要创建配置类,而@RabbitListener注解则可以将步骤简化;

注解操作为:生产者发送消息,创建监听器,在监听器注解中配置参数,主要参数为@RabbitListener(bindings (value,exchange,key))

  • 创建监听类,在注解中配置参数
@Component
public class Listen07 {
//    使用注解直接监听消息,以路由模式为例
//    监听器07
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "queue07",durable = "true"),
            exchange = @Exchange(name = "direct02_exchange",durable = "true",type = ExchangeTypes.DIRECT),
            key = {"error"}
    ))
    public void listen07(Message message){
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("consumer07----->"+s);
    }

//    监听器08
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "queue08",durable = "true"),
            exchange = @Exchange(name = "direct02_exchange"),
            key = {"error","info"}
    ))
    public void listen08(Message message){
        byte[] body = message.getBody();
        String s = new String(body);
        System.out.println("consumer08----->"+s);
    }
}
  • 创建测试类,模拟生产者发送消息
生产者6,测试使用注解监听消息,以订阅模式为例
    @Test
    public void test06(){
        rabbitTemplate.convertAndSend("direct02_exchange","error","测试error消息,7和8都要听到");
        rabbitTemplate.convertAndSend("direct02_exchange","info","测试info消息,8都要听到");
    }

 

5、总结

重点:     (1)RabbitMQ概念:是一个底层数据结构为队列的服务器;

                (2)RabbitMQ作用:实现系统之间的数据传输;

                (3)RabbitMQ应用:流量消峰,系统解耦,分发数据

                (4)RabbitMQ使用:熟练掌握以上五种模式的操作,熟练掌握注解的使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值