SpringBoot RabbitMq 并发与限流 应用

一.使用场景

电商中秒杀请求,属于瞬间大流量,同一时刻会有大量的请求涌入到系统中,可能导致系统挂掉。应付这种瞬间大流量的其中一种方式,便是利用消息队列。

二.用RabbitMQ 怎么处理

我们可以在“请求” -> “处理秒杀业务的接口” 中间架一层消息中间件做“缓冲”、“缓压”处理
在这里插入图片描述
默认情况一下,一个listener对应一个consumer,如果我们需要用 RabbitMQ 在 “请求” - “接口” 之间充当限流缓压的角色,那便需要我们对 RabbitMQ 提出更高的要求,即支持高并发的配置。一个listener 对应多个consumer。

三.rabbitmq-produce的改动

项目使用上一篇中的项目 rabbitmq-produce、rabbitmq-consumer

3.1 在rabbitmq-produce中,新增一个ConcurrentLimitRabbitConfig配置类

在 ConcurrentLimitRabbitConfig 里面 ,我们要定义多个消费者的监听器工厂

ConcurrentLimitRabbitConfig 的代码如下:

package com.example.rabbitmqproduce.config;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 *  并发、限流配置
 */
@Configuration
public class ConcurrentLimitRabbitConfig {

    private Logger logger = LoggerFactory.getLogger(ConcurrentLimitRabbitConfig.class);

    @Autowired
    private CachingConnectionFactory connectionFactory;

    public final static String queueName = "Queue";

    public static final String exchangeName = "exchange";

    private static final String bindingKey = "Routing";


    /**
     * 定义监听器工厂
     * 单一消费者
     * @return
     */
    @Bean(name = "singleListenerContainer")
    public SimpleRabbitListenerContainerFactory listenerContainer(){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        factory.setConcurrentConsumers(1);
        factory.setMaxConcurrentConsumers(1);
        factory.setPrefetchCount(1);
        factory.setTxSize(1);
        return factory;
    }


    /**
     * 定义监听器工厂
     * 多个消费者
     * @return
     */
    @Bean(name = "multiListenerContainer")
    public SimpleRabbitListenerContainerFactory multiListenerContainer(){
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setMessageConverter(new Jackson2JsonMessageConverter());
        //并发配置  最小5个,最大10个consumer
        factory.setConcurrentConsumers(5);
        factory.setMaxConcurrentConsumers(10);
        //限流配置   consumer单位时间内接收到消息就是50条
        factory.setPrefetchCount(50);
        return factory;
    }

    @Bean
    public Queue queue() {
        return new Queue(queueName);
    }

    @Bean
    public DirectExchange exchange() {
        return new DirectExchange(exchangeName);
    }

    @Bean
    public Binding binding() {
        return BindingBuilder.bind(queue()).to(exchange()).with(bindingKey);
    }
}

重点,是并发和限流的配置
在这里插入图片描述

3.2 新建一个消息生产者ConcurrentLimitProduce

ConcurrentLimitProduce 的代码如下:

package com.example.rabbitmqproduce.produce;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;


/**
 * 并发、限流
 */
@Component
public class ConcurrentLimitProduce {

    //注入一个AmqpTemplate来发布消息
    @Autowired
    private AmqpTemplate rabbitTemplate;

    private Logger logger = LoggerFactory.getLogger(ConcurrentLimitProduce.class);

    /**
     * 发送消息
     */
    public void sendMessage() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "hello!并发限流";
        String createTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        logger.info("发送的内容 : " + map.toString());
        //将消息携带绑定键值:directRouting 发送到交换机directExchange
        rabbitTemplate.convertAndSend("exchange", "Routing", map);
    }
}

三.rabbitmq-consumer的改动

3.1 新建一个消息消费者ConcurrentLimitConsumer类

ConcurrentLimitConsumer代码如下:

package com.example.rabbitmqconsumer.consumer;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Map;


/**
 * 并发、限流
 * @RabbitListener(queues = "Queue") 监听名为Queue的队列
 * 在@RabbitListener中,用containerFactory指定一个监听器工厂类 做并发、限流.
 * 这里用的是:
* containerFactory = “multiListenerContainer”
 */
@Component
@RabbitListener(queues = "Queue", containerFactory = "multiListenerContainer")
public class ConcurrentLimitConsumer {

    @Autowired
    private AmqpTemplate rabbitmqTemplate;

    private Logger logger = LoggerFactory.getLogger(ConcurrentLimitConsumer.class);

    /**
     * 消费消息
     * @RabbitHandler 代表此方法为接受到消息后的处理方法
     */
    @RabbitHandler
    public void receiveMessage(Map msg){
        logger.info("DirectExchange消费者接收到的消息 :" + msg.toString());
    }
}

重点:在@RabbitListener中,用containerFactory指定一个监听器工厂类 做并发、限流.
在这里插入图片描述

四.测试

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

刘德华一不小心就打代码

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

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

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

打赏作者

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

抵扣说明:

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

余额充值