SpringBoot2.x下RabbitMQ的并发参数(concurrency和prefetch)

点击上方“猿芯”,选择“设为星标

后台回复"1024",有份惊喜送给面试的你

RabbitMQ消费端配置

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    listener:
      simple:
#        acknowledge-mode: manual  # 手动确定(默认自动确认)
        concurrency: 1 # 消费端的监听个数(即@RabbitListener开启几个线程去处理数据。)
        max-concurrency: 10 # 消费端的监听最大个数
        prefetch: 10
    connection-timeout: 15000   # 超时时间

在消费端,配置prefetchconcurrency参数便可以实现消费端MQ并发处理消息,那么这两个参数到底有什么含义??

1. prefetch

每个customer会在MQ预取一些消息放入内存的LinkedBlockingQueue中,这个值越高,消息传递的越快,但非顺序处理消息的风险更高。如果ack模式为none,则忽略。如有必要,将增加此值以匹配txSize或messagePerAck。从2.0开始默认为250;设置为1将还原为以前的行为。

prefetch默认值以前是1,这可能会导致高效使用者的利用率不足。从spring-amqp 2.0版开始,默认的prefetch值是250,这将使消费者在大多数常见场景中保持忙碌,从而提高吞吐量。

不过在有些情况下,尤其是处理速度比较慢的大消息,消息可能在内存中大量堆积,消耗大量内存;以及对于一些严格要求顺序的消息,prefetch的值应当设置为1。

对于低容量消息和多个消费者的情况(也包括单listener容器的concurrency配置)希望在多个使用者之间实现更均匀的消息分布,建议在手动ack下并设置prefetch=1

模拟:
生产者每次生产10条消息:

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    publisher-confirms: true
    publisher-returns: true
@RestController
public class RabbitMQController {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    //直接向队列中发送数据
    @GetMapping("send")
    public String send() {
        for (int i = 0; i < 10; i++) {
            String content = "Date:" + System.currentTimeMillis();
            content = content + ":::" + i;
            rabbitTemplate.convertAndSend("kinson", content);
        }
        return "success";
    }
}

控制页面:

 

消费端直接预取了10条消息.png

2. concurrency

上面配置中,concurrency =1,即每个Listener容器将开启一个线程去处理消息。

在2.0版本后,可以在注解中配置该参数:

@Component
@Slf4j
public class CustomerRev {
  //会覆盖配置文件中的参数。
    @RabbitListener(queues = {"kinson"},concurrency =   "2")
    public void receiver(Message msg, Channel channel) throws InterruptedException {

//        Thread.sleep(10000);
        byte[] messageBytes = msg.getBody();

        if (messageBytes != null && messageBytes.length > 0) {
            //打印数据
            String message = new String(msg.getBody(), StandardCharsets.UTF_8);
            log.info("【消3】:{}", message);
        }
    }

}

启动服务:

 

可以看到MQ有两个消费者.png

即该Listener容器产生了两个线程去消费queue。如果在Listener配置了exclusive参数,即确定此容器中的单个customer是否具有对队列的独占访问权限。如果为true,则容器的并发性必须为1。

 


 

往期推荐

 

  1. 肝九千字长文 | MyBatis-Plus 码之重器 lambda 表达式使用指南,开发效率瞬间提升80%

  2. 用 MHA 做 MySQL 读写分离,频繁爆发线上生产事故后,泪奔分享 Druid 连接池参数优化实战

  3. 微服务架构下,解决数据库跨库查询的一些思路

  4. 一文读懂阿里大中台、小前台战略

作者简介猿芯,一枚简单的北漂程序员。喜欢用简单的文字记录工作与生活中的点点滴滴,愿与你一起分享程序员灵魂深处真正的内心独白。我的微信号:WooolaDunzung,公众号【猿芯输入 1024 ,有份面试惊喜送给你哦

< END >

【猿芯】

 微信扫描二维码,关注我的公众号。

分享不易,莫要干想,如果觉得有点用的话,动动你的发财之手,一键三连击:分享、点赞、在看,你们的鼓励是我分享优质文章的最强动力 ^_^

分享、点赞、在看,3连3连!

### Spring Boot集成RabbitMQ示例教程 #### 1. 添加依赖项 为了在Spring Boot项目中集成RabbitMQ,需要引入`spring-boot-starter-amqp`依赖。该依赖包含了与RabbitMQ交互所需的核心库[^1]。 在项目的`pom.xml`文件中添加如下内容: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> ``` #### 2. 配置RabbitMQ连接参数 在`application.yml`或`application.properties`文件中配置RabbitMQ的相关参数。以下是基于YAML格式的配置示例[^4]: ```yaml spring: rabbitmq: host: localhost # RabbitMQ服务器地址 port: 5672 # RabbitMQ服务端口 username: guest # 用户名 password: guest # 密码 virtual-host: / listener: simple: concurrency: 5 # 并发消费者数量 max-concurrency: 10 # 最大并发消费者数量 acknowledge-mode: manual # 手动ACK模式 prefetch: 1 # 每次预取的消息数 ``` #### 3. 创建RabbitMQ配置类 定义一个配置类用于声明队列、交换机绑定关系。以下是一个简单的配置示例[^3]: ```java import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Queue; import org.springframework.amqp.core.TopicExchange; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitConfig { public static final String QUEUE_NAME = "exampleQueue"; public static final String EXCHANGE_NAME = "exampleExchange"; @Bean public Queue queue() { return new Queue(QUEUE_NAME, true); // durable=true表示持久化队列 } @Bean public TopicExchange exchange() { return new TopicExchange(EXCHANGE_NAME); } @Bean public Binding binding(Queue queue, TopicExchange exchange) { return BindingBuilder.bind(queue).to(exchange).with("routing.key"); // 绑定路由键 } } ``` #### 4. 实现消息生产者 创建一个消息生产者类,负责向指定的队列发送消息。示例如下: ```java import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class MessageProducer { private final RabbitTemplate rabbitTemplate; @Autowired public MessageProducer(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; } public void sendMessage(String message) { rabbitTemplate.convertAndSend(RabbitConfig.EXCHANGE_NAME, "routing.key", message); System.out.println("Message sent: " + message); } } ``` #### 5. 实现消息消费者 创建一个消息消费者类,监听特定队列中的消息并处理它们。示例如下: ```java import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component public class MessageConsumer { @RabbitListener(queues = RabbitConfig.QUEUE_NAME) public void receiveMessage(String message) { System.out.println("Received message: " + message); } } ``` #### 6. 测试消息传递功能 启动Spring Boot应用后,可以通过调用`MessageProducer.sendMessage()`方法发送消息,并观察控制台输出验证消息是否被成功消费。 --- ### 总结 上述步骤涵盖了从环境搭建到实际使用的整个流程,包括依赖管理、配置文件编写、队列与交换机的定义以及消息生产消费的具体实现[^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值