Spring Boot整合RabbitMQ

1. 引言

在现代微服务架构中,消息队列已经成为系统解耦、异步处理和数据流控制的重要组件。Spring Boot作为Java生态中最受欢迎的企业级应用开发框架,与RabbitMQ的整合提供了强大而易用的消息处理能力。

本文将从基础概念开始,逐步介绍如何在Spring Boot项目中整合RabbitMQ,包括配置、五种工作模式的实现、高级特性以及最佳实践。

2. RabbitMQ基础回顾

2.1 核心组件

  • Producer(生产者):发送消息的客户端应用
  • Exchange(交换机):接收生产者消息,并根据路由规则分发到队列
  • Queue(队列):存储消息的容器
  • Consumer(消费者):接收消息的客户端应用
  • Binding(绑定):队列与交换机之间的连接,定义路由规则

2.2 交换机类型

  • Direct Exchange:直接交换机,根据RoutingKey完全匹配分发
  • Fanout Exchange:扇出交换机,广播模式,忽略RoutingKey
  • Topic Exchange:主题交换机,支持通配符匹配
  • Headers Exchange:头交换机,根据消息头属性匹配

3. Spring Boot项目搭建

3.1 创建Spring Boot项目

使用Spring Initializr或IDE创建项目,添加以下依赖:

<dependencies>
    <!-- Spring Boot Starter Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    
    <!-- Spring Boot Starter AMQP -->
    <dependency>
        <groupIdentity>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
    
    <!-- Spring Boot DevTools -->
    <dependency>
        <groupIdentity>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

3.2 配置文件

application.yml中配置RabbitMQ连接信息:

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    publisher-confirm-type: correlated
    publisher-returns: true
    templat:
      mandatory: true
server:
  port: 8080

4. 基础配置类

4.1 RabbitMQ配置类

package com.example.rabbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {

    // 消息序列化配置
    @Bean
    public Jackson2JsonMessageConverter messageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    // RabbitTemplate配置
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(messageConverter());
        
        // 开启确认模式
        template.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.println("消息发送成功");
            } else {
                System.out.println("消息发送失败:" + cause);
            }
        });
        
        // 开启返回模式
        template.setReturnsCallback(returned -> {
            System.out.println("消息被回退:" + returned.getMessage());
        });
        
        return template;
    }

    // 监听器容器工厂配置
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
            ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(messageConverter());
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL); // 手动确认
        return factory;
    }
}

5. 简单模式(Simple)

5.1 消息实体类

package com.example.rabbitmq.dto;

import java.io.Serializable;
import java.time.LocalDateTime;

public class OrderMessage implements Serializable {
    private Long orderId;
    private String productName;
    private Integer quantity;
    private LocalDateTime createTime;
    
    // 构造函数、getter、setter省略
}

5.2 生产者

package com.example.rabbitmq.producer;

import com.example.rabbitmq.dto.OrderMessage;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.UUID;

@Component
public class OrderProducer {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    public void sendOrderMessage(String orderInfo) {
        // 创建消息属性
        MessageProperties properties = new MessageProperties();
        properties.setContentType("application/json");
        properties.setDeliveryMode(2); // 持久化消息
        
        // 创建消息对象
        OrderMessage orderMessage = new OrderMessage();
        orderMessage.setOrderId(System.currentTimeMillis());
        orderMessage.setProductName("iPhone 15");
        orderMessage.setQuantity(1);
        orderMessage.setCreateTime(LocalDateTime.now());
        
        // 发送消息
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend("simple.queue", "simple.routing.key", 
                                     orderMessage, correlationData);
        
        System.out.println("订单消息发送成功:" + orderMessage);
    }
}

5.3 消费者

package com.example.rabbitmq.consumer;

import com.example.rabbitmq.dto.OrderMessage;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class OrderConsumer {
    
    @RabbitListener(queues = "simple.queue")
    public void handleOrderMessage(OrderMessage orderMessage, Channel channel, Message message) {
        try {
            System.out.println("接收到订单消息:" + orderMessage);
            
            // 业务处理逻辑
            processOrder(orderMessage);
            
            // 手动确认消息
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            
        } catch (Exception e) {
            System.err.println("订单处理失败:" + e.getMessage());
            try {
                // 拒绝消息,不重新入队
                channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    
    private void processOrder(OrderMessage orderMessage) {
        // 模拟订单处理
        System.out.println("正在处理订单:" + orderMessage.getOrderId());
        // 这里可以调用订单服务、库存服务等
    }
}

5.4 队列声明

package com.example.rabbitmq.config;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SimpleConfig {
    
    @Bean
    public Queue simpleQueue() {
        return QueueBuilder.durable("simple.queue")
                .build();
    }
}

6. 工作队列模式(Work Queue)

6.1 配置类

package com.example.rabbitmq.config;

import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.QueueBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WorkQueueConfig {
    
    @Bean
    public Queue workQueue() {
        return QueueBuilder.durable("work.queue")
                .build();
    }
}

6.2 消费者实现

package com.example.rabbitmq.consumer;

import com.example.rabbitmq.dto.OrderMessage;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class WorkConsumer {
    
    @RabbitListener(queues = "work.queue")
    public void worker1(OrderMessage orderMessage, Channel channel, Message message) throws Exception {
        System.out.println("Worker1 处理订单:" + orderMessage.getOrderId());
        
        // 模拟处理时间
        Thread.sleep(1000);
        
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
    
    @RabbitListener(queues = "work.queue")
    public void worker2(OrderMessage orderMessage, Channel channel, Message message) throws Exception {
        System.out.println("Worker2 处理订单:" + orderMessage.getOrderId());
        
        // 模拟处理时间
        Thread.sleep(1000);
        
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}

7. 发布订阅模式(Publish/Subscribe)

7.1 广播交换机和队列配置

package com.example.rabbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FanoutConfig {
    
    // 声明广播交换机
    @Bean
    public FanoutExchange fanoutExchange() {
        return return ExchangeBuilder.fanoutExchange("broadcast.exchange")
                .durable(true)
                .build();
    }
    
    // 邮件队列
    @Bean
    public Queue emailQueue() {
        return QueueBuilder.durable("email.queue")
                .build();
    }
    
    // 短信队列
    @Bean
    public Queue smsQueue() {
        return QueueBuilder.durable("sms.queue")
                .build();
    }
    
    // 站内信队列
    @Bean
    public Queue stationQueue() {
        return QueueBuilder.durable("station.queue")
                .build();
    }
    
    // 绑定邮件队列
    @Bean
    public Binding emailBinding() {
        return BindingBuilder.bind(emailQueue())
                .to(fanoutExchange());
    }
    
    // 绑定短信队列
    @Bean
    public Binding smsBinding() {
        return BindingBuilder.bind(smsQueue())
                .to(fanoutExchange());
    }
    
    // 绑定站内信队列
    @Bean
    public Binding stationBinding() {
        return BindingBuilder.bind(stationQueue())
                .to(fanoutExchange());
    }
}

7.2 消息和消费者

package com.example.rabbitmq.dto;

import java.io.Serializable;

public class PromotionMessage implements Serializable {
    private String title;
    private String content;
    private Long userId;
    private String type; // email, sms, station
    
    // 构造函数、getter、setter省略
}
package com.example.rabbitmq.producer;

import com.example.rabbitmq.dto.PromotionMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class PromotionProducer {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    public void broadcastPromotion(String title, String content, Long userId) {
        PromotionMessage message = new PromotionMessage();
        message.setTitle(title);
        message.setContent(content);
        message.setUserId(userId);
        
        // 发送到广播交换机,忽略routing key
        rabbitTemplate.convertAndSend("broadcast.exchange", "", message);
        
        System.out.println("促销消息广播成功:" + title);
    }
}
package com.example.rabbitmq.consumer;

import com.example.rabbitmq.dto.PromotionMessage;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class PromotionConsumer {
    
    @RabbitListener(queues = "email.queue")
    public void emailConsumer(PromotionMessage message, Channel channel, Message msg) throws Exception {
        System.out.println("发送邮件:" + message.getTitle());
        // 邮件服务逻辑
        channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
    }
    
    @RabbitListener(queues = "sms.queue")
    public void smsConsumer(PromotionMessage message, Channel channel, Message msg) throws Exception {
        System.out.println("发送短信:" + message.getTitle());
        // 短信服务逻辑
        channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
    }
    
    @RabbitListener(queues = "station.queue")
    public void stationConsumer(PromotionMessage message, Channel channel, Message msg) throws Exception {
        System.out.println("发送站内信:" + message.getTitle());
        // 站内信服务逻辑
        channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
    }
}

8. 路由模式(Routing)

8.1 直接交换机和路由配置

package com.example.rabbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RoutingConfig {
    
    // 声明直接交换机
    @Bean
    public DirectExchange directExchange() {
        return ExchangeBuilder.directExchange("log.exchange")
                .durable(true)
                .build();
    }
    
    // 错误日志队列
    @Bean
    public Queue errorQueue() {
        return QueueBuilder.durable("error.log.queue").build();
    }
    
    // 警告日志队列
    @Bean
    public Queue warningQueue() {
        return QueueBuilder.durable("warning.log.queue").build();
    }
    
    // 信息日志队列
    @Bean
    public Queue infoQueue() {
        return QueueBuilder.durable("info.log.queue").build();
    }
    
    // 绑定错误日志队列
    @Bean
    public Binding errorBinding() {
        return BindingBuilder.bind(errorQueue())
                .to(directExchange())
                .with("error");
    }
    
    // 绑定警告日志队列
    @Bean
    public Binding warningBinding() {
        return BindingBuilder.bind(warningQueue())
                .to(directExchange())
                .with("warning");
    }
    
    // 绑定信息日志队列
    @Bean
    public Binding infoBinding() {
        return BindingBuilder.bind(infoQueue())
                .to(directExchange())
                .with("info");
    }
}

8.2 日志服务和消费者

package com.example.rabbitmq.dto;

import java.io.Serializable;
import java.time.LocalDateTime;

public class LogMessage implements Serializable {
    private String level; // error, warning, info
    private String message;
    private String source;
    private LocalDateTime timestamp;
    
    // 构造函数、getter、setter省略
}
package com.example.rabbitmq.producer;

import com.example.rabbitmq.dto.LogMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class LogProducer {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    public void logError(String message, String source) {
        LogMessage logMessage = new LogMessage();
        logMessage.setLevel("error");
        logMessage.setMessage(message);
        logMessage.setSource(source);
        logMessage.setTimestamp(LocalDateTime.now());
        
        rabbitTemplate.convertAndSend("log.exchange", "error", logMessage);
        System.out.println("错误日志发送成功");
    }
    
    public void logWarning(String message, String source) {
        LogMessage logMessage = new LogMessage();
        logMessage.setLevel("warning");
        logMessage.setMessage(message);
        logMessage.setSource(source);
        logMessage.setTimestamp(LocalDateTime.now());
        
        rabbitTemplate.convertAndSend("log.exchange", "warning", logMessage);
        System.out.println("警告日志发送成功");
    }
    
    public void logInfo(String message, String source) {
        LogMessage logMessage = new LogMessage();
        logMessage.setLevel("info");
        logMessage.setMessage(message);
        logMessage.setSource(source);
        logMessage.setTimestamp(LocalDateTime.now());
        
        rabbitTemplate.convertAndSend("log.exchange", "info", logMessage);
        System.out.println("信息日志发送成功");
    }
}

9. 主题模式(Topic)

9.1 主题交换机配置

package com.example.rabbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TopicConfig {
    
    // 声明主题交换机
    @Bean
    public TopicExchange topicExchange() {
        return ExchangeBuilder.topicExchange("news.exchange")
                .durable(true)
                .build();
    }
    
    // 体育新闻队列
    @Bean
    public Queue sportsQueue() {
        return QueueBuilder.durable("sports.news.queue").build();
    }
    
    // 财经新闻队列
    @Bean
    public Queue financeQueue() {
        return QueueBuilder.durable("finance.news.queue").build();
    }
    
    // 科技新闻队列
    @Bean
    public Queue techQueue() {
        return QueueBuilder.durable("tech.news.queue").build();
    }
    
    // 绑定体育队列 (*.sports.*)
    @Bean
    public Binding sportsBinding() {
        return BindingBuilder.bind(sportsQueue())
                .to(topicExchange())
                .with("*.sports.*");
    }
    
    // 绑定财经队列 (*.finance.*)
    @Bean
    public Binding finance-binding() {
        return BindingBuilder.bind(financeQueue())
                .to(topicExchange())
                .with("*.finance.*");
    }
    
    // 绑定科技队列 (*.tech.*)
    @Bean
    public Binding techBinding() {
        return BindingBuilder.bind(techQueue())
                .to(topicExchange())
                .with("*.tech.*");
    }
}

9.2 新闻服务和消费者

package com.example.rabbitmq.dto;

import java.io.Serializable;

public class NewsMessage implements Serializable {
    private String category;
    private String title;
    private String content;
    private String source;
    
    // 构造函数、getter、setter省略
}
package com.example.rabbitmq.producer;

import com.example.rabbitmq.dto.NewsMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class NewsProducer {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    public void publishSportsNews(String title, String content, String source) {
        NewsMessage news = new NewsMessage();
        news.setCategory("sports");
        news.setTitle(title);
        news.setContent(content);
        news.setSource(source);
        
        rabbitTemplate.convertAndSend("news.exchange", "china.sports.football", news);
        System.out.println('体育新闻发布成功:' + title);
    }
    
    public void publishFinanceNews(String title, String content, String source) {
        NewsMessage news = new NewsMessage();
        news.setCategory("finance");
        news.setTitle(title);
        news.setContent(content);
        news.setSource(source);
        
        rabbitTemplate.convertAndSend("news.exchange", "china.finance.stock", news);
        System.out.println("财经新闻发布成功:" + title);
    }
    
    public void publishTechNews(String title, String content, String source) {
        NewsMessage news = new NewsMessage();
        news.setCategory("tech");
        news.setTitle(title);
        news.setContent(content);
        news.setSource(source);
        
        rabbitTemplate.convertAndSend("news.exchange", "usa.tech.ai", news);
        System.out.println("科技新闻发布成功:" + title);
    }
}

10. 高级特性

10.1 延迟队列实现

package com.example.rabbitmq.config;

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DelayConfig {
    
    // 延迟交换机
    @Bean
    public DirectExchange delayExchange() {
        return ExchangeBuilder.directExchange("delay.exchange")
                .durable(true)
                .build();
    }
    
    // 延迟队列
    @Bean
    public Queue delayQueue() {
        return QueueBuilder.durable("delay.queue")
                .withArgument("x-message-ttl", 60000) // TTL 60秒
                .withArgument("x-dead-letter-exchange", "dead.exchange")
                .withArgument("x-dead-letter-routing-key", "dead")
                .build();
    }
    
    // 死信队列
    @Bean
    public Queue deadQueue() {
        return QueueBuilder.durable("dead.queue").build();
    }
    
    @Bean
    public DirectExchange deadExchange() {
        return ExchangeBuilder.directExchange("dead.exchange")
                .durable(true)
                .build();
    }
    
    @Bean
    public Binding delayBinding() {
        return BindingBuilder.bind(delayQueue())
                .to(delayExchange())
                .with("delay");
    }
    
    @Bean
    public Binding deadBinding() {
        return BindingBuilder.bind(deadQueue())
                .to(deadExchange())
                .with("dead");
    }
}

10.2 消费者限流

package com.example.rabbitmq.config;

import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AdvancedConfig {
    
    @Bean
    public SimpleRabbitListenerContainerFactory advancedContainerFactory(
            ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        
        // 预拉取数量,控制并发
        factory.setPrefetchCount(1);
        
        // 消费者数量
        factory.setConcurrentConsumers(3);
        factory.setMaxConcurrentConsumers(10);
        
        return factory;
    }
}

10.3 死信队列处理

package com.example.rabbitmq.consumer;

import com.example.rabbitmq.dto.OrderMessage;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class DeadLetterConsumer {
    
    @RabbitListener(queues = "dead.queue")
    public void handleDeadLetter(OrderMessage message, Channel channel, Message msg) throws Exception {
        System.out.println("处理死信消息:" + message);
        
        // 记录失败信息到数据库
        recordFailure(message);
        
        channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
    }
    
    private void recordFailure(OrderMessage message) {
        // 记录失败逻辑
        System.out.println("订单处理失败,已记录:" + message.getOrderId());
    }
}

11. 控制器和测试

11.1 REST API控制器

package com.example.rabbitmq.controller;

import com.example.rabbitmq.dto.OrderMessage;
import com.example.rabbitmq.producer.OrderProducer;
import com.example.rabbitmq.producer.LogProducer;
import com.example.rabbitmq.producer.PromotionProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/mq")
public class MQController {
    
    @Autowired
    private OrderProducer orderProducer;
    
    @Autowired
    private LogProducer logProducer;
    
    @Autowired
    private PromotionProducer promotionProducer;
    
    @PostMapping("/order")
    public String sendOrder(@RequestParam String productName, @RequestParam Integer quantity) {
        orderProducer.sendOrderMessage("订单信息:" + productName + "," + quantity);
        return "订单消息发送成功";
    }
    
    @PostMapping("/log")
    public String sendLog(@RequestParam String level, 
                         @RequestParam String message,
                         @RequestParam String source) {
        switch (level.toLowerCase()) {
            case "error":
                logProducer.logError(message, source);
                break;
            case "warning":
                logProducer.logWarning(message, source);
                break;
            case "info":
                logProducer.logInfo(message, source);
                break;
            default:
                return "无效的日志级别";
        }
        return "日志消息发送成功";
    }
    
    @PostMapping("/promotion")
    public String broadcastPromotion(@RequestParam String title,
                                   @RequestParam String content,
                                   @RequestParam Long userId) {
        promotionProducer.broadcastPromotion(title, content, userId);
        return "促销消息广播成功";
    }
}

11.2 测试用例

package com.example.rabbitmq;

import com.example.rabbitmq.producer.OrderProducer;
import com.example.rabbitmq.producer.LogProducer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class RabbitMQTest {
    
    @Autowired
    private OrderProducer orderProducer;
    
    @Autowired
    private LogProducer logProducer;
    
    @Test
    public void testSendOrder() {
        orderProducer.sendOrderMessage("测试订单");
    }
    
    @Test
    public void testSendLogs() {
        logProducer.logError("系统错误", "UserController");
        logProducer.logWarning("内存使用率过高", "SystemMonitor");
        logProducer.logInfo("用户登录成功", "AuthService");
    }
}

12. 最佳实践

12.1 性能优化建议

  1. 连接池配置
spring:
  rabbitmq:
    connection-timeout: 15000
    requested-heartbeat: 30
    publisher-confirm-type: correlated
    publisher-returns: true
    listener:
      simple:
        concurrency: 3
        max-concurrency: 10
        prefetch: 1
        acknowledge-mode: manual
  1. 消息可靠性保证
  • 启用消息确认机制
  • 使用持久化消息和队列
  • 实现幂等性处理
  • 设置合理的重试机制
  1. 监控和日志
package com.example.rabbitmq.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Slf4j
public class MonitoringConfig {
    
    @Bean
    public RabbitTemplate monitoringRabbitTemplate(ConnectionFactory connectionFactory,
                                                   MessageConverter messageConverter) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(messageConverter);
        
        // 发送确认回调
        template.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("消息发送成功:{}", correlationData.getId());
            } else {
                log.error("消息发送失败:{}, 原因:{}", correlationData.getId(), cause);
            }
        });
        
        // 发送返回回调
        template.setReturnsCallback(returned -> {
            log.error("消息被返回:{}", returned.getMessage());
        });
        
        return template;
    }
}

12.2 错误处理

package com.example.rabbitmq.handler;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.listener.ConditionalRejectingErrorHandler;
import org.springframework.amqp.rabbit.listener.FatalExceptionStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@Slf4j
public class ErrorHandlerConfig {
    
    @Bean
    public ConditionalRejectingErrorHandler errorHandler() {
        return new ConditionalRejectingErrorHandler(new FatalExceptionStrategy());
    }
    
    // 全局异常处理器
    @SlbitListener
    public void handleErrors(Exception exception, Channel channel, Message message) {
        log.error("消息处理异常:{}", exception.getMessage(), exception);
        
        try {
            // 实现重试逻辑或发送到死信队列
            retryOrSendToDeadLetter(message, channel);
        } catch (Exception e) {
            log.error("错误处理失败:{}", e.getMessage());
        }
    }
    
    private void retryOrSendToDeadLetter(Message message, Channel channel) throws Exception {
        // 重试逻辑或死信队列处理
        channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
    }
}

13. 总结

本文详细介绍了Spring Boot与RabbitMQ的整合方案,涵盖了从基础配置到高级特性的完整实现。通过五种工作模式的实际应用,展示了RabbitMQ在不同场景下的最佳实践。

关键要点:

  1. 配置简化:Spring Boot自动配置功能大大简化了RabbitMQ的集成
  2. 模式灵活:根据不同业务场景选择合适的工作模式
  3. 可靠性:通过确认机制、持久化、重试等保证消息可靠性
  4. 性能优化:合理配置连接池、并发控制、预取数量等参数
  5. 监控告警:完善的日志记录和异常处理机制

Spring Boot与RabbitMQ的组合为构建高可用、高性能的分布式系统提供了强大的消息处理能力,是现代化企业应用开发的重要技术栈。


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

程序员小凯

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

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

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

打赏作者

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

抵扣说明:

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

余额充值