SpringBoot整合RabbitMQ完成应用解耦和延时任务

前言:
MQ 是什么?队列是什么,MQ 我们可以理解为消息队列,队列我们可以理解为管道。以管道的方式做消息传递。

场景:

1.优化用户体验,当我们在网上购物结算时,就会发现,界面会提醒我们,让我们稍等,以及一些友好的图片文字提醒
    
2.在我们平时的超市中购物也,遇到大批人一窝蜂一样涌入收银台,怎么办?所以超时,会设置一个走廊,让人们排队一个一个慢慢结算。
在网络购物中也会遇到同样的情况,MQ就会帮我们解决这个问题。

在这里插入图片描述
RabbitMQ模式
1.简单模式:非常简单的模式,一发一收

2.工作模式 :与简单模式一样只是有多个消费者,采用轮询模式,但是资源分配不公平

3.公平模式:资源分配公平的工作模式

4.订阅模式:消息产生者将消息通过交换机放入队列,对应消息队列的消费者拿到消息进行消费

5.路由模式:与订阅模式一样,只是绑定队列时,加入了路由键

6.主题模式:与路由模式一样,只是路由键可以进行模糊匹配。像SQL语句中的 like% 和like%


SpringBoot整合RabbitMQ

  • 直接进入正题,这里先写平时用的最多的路由键模式,其他模式以后补上来

POM依赖

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

application配置

#rabbitmq配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=miro
spring.rabbitmq.password=xxxxx
spring.rabbitmq.virtual-host=mirovh

绑定交换机设置config类

@Configuration
public class RouteConfig {

    //声明交换机
    @Bean
    public DirectExchange directExchange(){
        return  new DirectExchange("direct-ex");   //交换机的名字direct-ex
    }

    //创建队列  2个队列就要2个消费者
    @Bean
    public Queue directQueue1(){
        return  new Queue("direct-queue1");   //队列1的名字direct-queue1
    }

    @Bean
    public Queue directQueue2(){
        return  new Queue("direct-queue2");   //队列2的名字direct-queue2
    }

    //绑定队列到交换机的路由键上面
    @Bean
    public Binding bindingDirectExchange1(){
        return BindingBuilder.bind(directQueue1()).to(directExchange()).with("dq1");//路由键名字dq1
    }

    @Bean
    public Binding bindingDirectExchange2(){
        return BindingBuilder.bind(directQueue2()).to(directExchange()).with("dq2");//路由键名字dq2
    }


}

Controller层

@RestController
public class rabbitController {
    @Resource
    private AmqpTemplate amqpTemplate; //使用AmqpTemplate ,这提供了接收/发送等等方法


    @RequestMapping("direct1")
    public String direct1(String data){
        amqpTemplate.convertAndSend("direct-ex","dq1",data);   //三个参数为  交换机的名字direct-ex,路由键的名字dq1,数据
        return "success";
    }

    @RequestMapping("direct2")
    public String direct2(String data){
        amqpTemplate.convertAndSend("direct-ex","dq2",data);
        return "success";
    }
    
}

监听队列

@Configuration
public class RouteConsumer {

    @Resource
    private ConnectionFactory connectionFactory;
    //手动定义消费者进行消息确认


    @Bean
    public SimpleMessageListenerContainer DirectContainer1(){

        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        //当前监听器容器监听的队列
        //放入的是上面的工作队列
        container.setQueueNames("direct-queue1");  //这里写入要接受消息的队列
        //监听通道
        container.setExposeListenerChannel(true);
        //设置最大并发消费者数量--最终上线
        container.setMaxConcurrentConsumers(10);
        //设置当前并发消费者数量--代码可以动态调整数量
        container.setConcurrentConsumers(1);
        //修改为手动确认模式
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);//消息确认后才能删除
        //一个消费者每次处理一条数据
        container.setPrefetchCount(1);
        //定义一个监听
        container.setMessageListener(new ChannelAwareMessageListener() {
            //从队列中读取消息的方法
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
                byte[] bytes = message.getBody();
                String data = new String(bytes);
                System.out.println("路由键模式消费者1处理消息"+data);
                //这里进行数据库的操作
                //确认消息已被处理
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            }
        });
        return container;
    }
    
   	@Bean
    public SimpleMessageListenerContainer DirectContainer2(){

        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        //当前监听器容器监听的队列
        //放入的是上面的工作队列
        container.setQueueNames("direct-queue2");
        //监听通道
        container.setExposeListenerChannel(true);
        //设置最大并发消费者数量--最终上线
        container.setMaxConcurrentConsumers(10);
        //设置当前并发消费者数量--代码可以动态调整数量
        container.setConcurrentConsumers(1);
        //修改为手动确认模式
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);//消息确认后才能删除
        //一个消费者每次处理一条数据
        container.setPrefetchCount(1);
        //定义一个监听
        container.setMessageListener(new ChannelAwareMessageListener() {
            //从队列中读取消息的方法
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
                byte[] bytes = message.getBody();
                String data = new String(bytes);
                System.out.println("路由键模式消费者2处理消息"+data);
                   //这里进行数据库的操作
                //确认消息已被处理
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            }
        });
        return container;
    }
    
}

测试

在这里插入图片描述
在这里插入图片描述


死信队列机制实现延时任务

解决问题在这里插入图片描述

@Configuration
public class DelayConfig {
    //配置死信队列
    @Bean
    public Queue delayQueue(){
        Map<String,Object>params = new HashMap<>();
        //定义死信的时间,单位毫秒
        params.put("x-message-ttl",5 * 1000);
        //x-dead-letter-exchange 是属性 后面跟的值是死信要发送到的交换机名字
        params.put("x-dead-letter-exchange","delay-ex");
        //-dead-letter-routing-key 是属性 后面跟的值是这些死信在转发时携带的路由键名称
        params.put("x-dead-letter-routing-key","order");
        return  new Queue("delay-queue",true,false,false,params);

    }
    //交换机
    @Bean
    public DirectExchange delayExchange(){
        return  new DirectExchange("delay-ex");
    }
    //创建保存死信信息的队列
    @Bean
    public Queue orderQueue1(){
        return  new Queue("order-queue");
    }
    //将order队列绑定到delay-ex 交换机的order路由键下面
    @Bean
    public Binding bindingToDelayExchange1(){
        return BindingBuilder.bind(orderQueue1()).to(delayExchange()).with("order");//路由键名字dq1
    }

    @Resource
    private ConnectionFactory connectionFactory;
    //手动定义消费者进行消息确认
    @Bean
    public SimpleMessageListenerContainer oderContainer1(){

        SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
        //当前监听器容器监听的队列
        //放入的是上面的工作队列
        container.setQueues(orderQueue1());
        //监听通道
        container.setExposeListenerChannel(true);
        //设置最大并发消费者数量--最终上线
        container.setMaxConcurrentConsumers(10);
        //设置当前并发消费者数量--代码可以动态调整数量
        container.setConcurrentConsumers(1);
        //修改为手动确认模式
        container.setAcknowledgeMode(AcknowledgeMode.MANUAL);//消息确认后才能删除
        //一个消费者每次处理一条数据
        container.setPrefetchCount(1);
        //定义一个监听
        container.setMessageListener(new ChannelAwareMessageListener() {
            //从队列中读取消息的方法
            @Override
            public void onMessage(Message message, Channel channel) throws Exception {
                byte[] bytes = message.getBody();
                String data = new String(bytes);
                System.out.println("延迟模式消费者处理消息"+data);
                //确认消息已被处理
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            }
        });
        return container;
    }


}

Controller层

@RequestMapping("delay")
public String delay(String data){
    amqpTemplate.convertAndSend("delay-queue",data);
    return "success";
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值