1. Spring Boot 集成 RabbitMQ 批量发送、消费消息
1.1. 版本说明
构件 |
版本 |
spring-boot |
2.7.18 |
spring-boot-starter-amqp |
2.7.18 |
1.2. Spring 配置
| spring: |
| application: |
| name: spring-rabbit-batch-demo |
| rabbitmq: |
| addresses: 127.0.0.1:5672 |
| username: admin |
| password: admin |
| virtual-host: / |
1.3. 定义常量
| public class RabbitBatchConstants { |
| public static final String QUEUE_1 = "spring-rabbit-batch-demo-queue-1"; |
| public static final String EXCHANGE_1 = "spring-rabbit-batch-demo-exchange-1"; |
| public static final String QUEUE_2 = "spring-rabbit-batch-demo-queue-2"; |
| public static final String EXCHANGE_2 = "spring-rabbit-batch-demo-exchange-2"; |
| } |
1.4. 配置交换机和队列
| @Configuration |
| @Slf4j |
| public class RabbitBatchConfiguration { |
| |
| @Bean |
| public Queue queue1() { |
| return QueueBuilder.durable(RabbitBatchConstants.QUEUE_1).build(); |
| } |
| |
| @Bean |
| public FanoutExchange exchange1() { |
| return ExchangeBuilder.fanoutExchange(RabbitBatchConstants.EXCHANGE_1).durable(true).build(); |
| } |
| |
| @Bean |
| public Queue queue2() { |
| return QueueBuilder.durable(RabbitBatchConstants.QUEUE_2).build(); |
| } |
| |
| @Bean |
| public FanoutExchange exchange2() { |
| return ExchangeBuilder.fanoutExchange(RabbitBatchConstants.EXCHANGE_2).durable(true).build(); |
| } |
| |
| @Bean |
| public Binding binding1() { |
| return BindingBuilder.bind(queue1()).to(exchange1()); |
| } |
| |
| @Bean |
| public Binding binding2() { |
| return BindingBuilder.bind(queue2()).to(exchange2()); |
| } |
| } |
1.5. 定义 BatchingRabbitTemplate 工厂
org.springframework.amqp.rabbit.core.BatchingRabbitTemplate
提供了批量发送消息的 API,但是一个 BatchingRabbitTemplate
实例只能发送同一交换机或 Routing Key 的消息,因此需要一个工厂类,针对同一交换机生成一个 BatchingRabbitTemplate
实例。
定义 TaskScheduler:
| @Bean(name = "rabbitBatchTaskScheduler") |
| TaskScheduler taskScheduler() { |
| ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); |
| threadPoolTaskScheduler.setPoolSize(Runtime.getRuntime().availableProcessors() * 2); |
| threadPoolTaskScheduler.setThreadNamePrefix("rabbit-batch-"); |
| threadPoolTaskScheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); |
| threadPoolTaskScheduler.initialize(); |
| return threadPoolTaskScheduler; |
| } |
定义 BatchingRabbitTemplate 工厂:
| @Component |
| public class BatchingRabbitTemplateFactory implements Lifecycle { |
| |
| @Resource |
| private ConnectionFactory connectionFactory; |
| |
| @Resource(name = "rabbitBatchTaskScheduler") |
| private TaskScheduler taskScheduler; |
| |
| private Map<String, BatchingRabbitTemplate> batchingRabbitTemplateMap = new ConcurrentHashMap<>(); |
| |
| public BatchingRabbitTemplate getBatchingRabbitTemplate(String exchange) { |
| return batchingRabbitTemplateMap.computeIfAbsent(exchange, exchangeName -> { |
| |
| return new BatchingRabbitTemplate(connectionFactory, new SimpleBatchingStrategy(100, 1024 * 1000, 1000L), taskScheduler); |
| }); |
| } |
| |
| @Override |
| public void start() { |
| |
| } |
| |
| @Override |
| public void stop() { |
| batchingRabbitTemplateMap.forEach((exchange, batchingRabbitTemplate) -> batchingRabbitTemplate.stop()); |
| } |
| |
| @Override |
| public boolean isRunning() { |
| return true; |
| } |
| } |
1.6. 配置批量消费消息的 RabbitListenerContainerFactory
| @Bean(name = "batchRabbitListenerContainerFactory") |
| SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(ConnectionFactory connectionFactory) { |
| SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); |
| factory.setConnectionFactory(connectionFactory); |
| |
| factory.setBatchListener(true); |
| |
| factory.setBatchSize(100); |
| return factory; |
| } |
1.7. 测试
| @Component |
| @Slf4j |
| public class SpringRabbitBatchDemo implements ApplicationRunner { |
| |
| @Resource |
| private BatchingRabbitTemplateFactory batchingRabbitTemplateFactory; |
| |
| @Override |
| public void run(ApplicationArguments args) throws Exception { |
| String payload1 = "hello, queue 1"; |
| for (int i = 0; i < 100; i++) { |
| batchingRabbitTemplateFactory.getBatchingRabbitTemplate(EXCHANGE_1).convertAndSend(EXCHANGE_1, null, payload1); |
| } |
| log.info("send 100 messages, exchange: {}, payload: {}", EXCHANGE_1, payload1); |
| |
| String payload2 = "hello, queue 2"; |
| for (int i = 0; i < 2; i++) { |
| batchingRabbitTemplateFactory.getBatchingRabbitTemplate(EXCHANGE_2).convertAndSend(EXCHANGE_2, null, payload2); |
| } |
| log.info("send 2 messages, exchange: {}, payload: {}", EXCHANGE_2, payload2); |
| } |
| |
| |
| |
| |
| |
| @RabbitListener(queues = {RabbitBatchConstants.QUEUE_1}, containerFactory = "batchRabbitListenerContainerFactory") |
| public void listen1(List<Message<String>> messages) { |
| log.info( |
| "queue 1 received {} messages", |
| messages.size() |
| ); |
| } |
| |
| |
| |
| |
| |
| @RabbitListener(queues = {RabbitBatchConstants.QUEUE_2}) |
| public void listen2(Message<String> message) { |
| log.info("queue 2 received a message"); |
| } |
| } |
启动程序,控制台将输出:
| send 100 messages, exchange: spring-rabbit-batch-demo-exchange-1, payload: hello, queue 1 |
| send 2 messages, exchange: spring-rabbit-batch-demo-exchange-2, payload: hello, queue 2 |
| queue 1 received 100 messages |
| queue 2 received a message |
| queue 2 received a message |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)