RabbitMQ 在 Spring Boot 项目中的完整配置指南

一、Maven 依赖

xml 复制代码
<!-- RabbitMQ 核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

<!-- 可选:JSON 序列化 -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>

二、基础配置(application.yml)

yaml 复制代码
spring:
  rabbitmq:
    # ==================== 连接配置 ====================
    host: localhost               # RabbitMQ 服务器地址
    port: 5672                    # 端口,默认5672
    username: guest               # 用户名,默认guest
    password: guest               # 密码,默认guest
    virtual-host: /               # 虚拟主机,默认/
    
    # ==================== 连接池配置 ====================
    # 使用连接池(需要引入spring-boot-starter-amqp依赖)
    connection:
      name: rabbitmq-connection   # 连接名称
      factory:
        cache-mode: CHANNEL       # 连接缓存模式:CHANNEL(默认)或CONNECTION
        channel-cache-size: 25    # 每个连接缓存的通道数
        channel-checkout-timeout: 10000 # 获取通道超时时间(ms)
    
    # ==================== 连接重试配置 ====================
    connection-timeout: 60000     # 连接超时时间(ms)
    requested-heartbeat: 60       # 心跳超时时间(秒)
    
    # 自动重连配置
    retry:
      enabled: true               # 开启重试机制
      max-attempts: 3             # 最大重试次数
      initial-interval: 1000      # 初始重试间隔(ms)
      multiplier: 1.0             # 重试间隔乘数
      max-interval: 10000         # 最大重试间隔(ms)
    
    # ==================== 消息确认配置 ====================
    publisher-confirms: true      # 已废弃,使用publisher-confirm-type
    publisher-confirm-type: correlated  # 发布者确认模式
    # 可选值:
    #   none: 禁用
    #   simple: 同步确认(性能差)
    #   correlated: 异步确认(推荐)
    
    publisher-returns: true       # 开启发布者返回模式
    template:
      mandatory: true             # 强制消息路由
    
    # ==================== 消费者配置 ====================
    listener:
      simple:
        acknowledge-mode: manual  # 确认模式:AUTO(自动), MANUAL(手动), NONE(不确认)
        prefetch: 10              # 每个消费者最大预取消息数
        concurrency: 5            # 最小并发消费者数
        max-concurrency: 10       # 最大并发消费者数
        retry:
          enabled: true           # 开启消费者重试
          max-attempts: 3         # 最大重试次数
          initial-interval: 1000  # 重试间隔
          max-interval: 10000     # 最大重试间隔
          multiplier: 1.0         # 间隔乘数
          stateless: true         # 是否为无状态重试
        
        # 消费者异常处理
        default-requeue-rejected: false  # 是否重新入队被拒绝的消息
        missing-queues-fatal: false      # 队列不存在是否致命
        idle-event-interval: 60000       # 空闲事件间隔(ms)

三、高级配置类(Java Config)

java 复制代码
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.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.ObjectMapper;

@Configuration
public class RabbitMQConfig {
    
    // ==================== 队列、交换机、路由键定义 ====================
    public static final String DIRECT_EXCHANGE = "direct.exchange";
    public static final String TOPIC_EXCHANGE = "topic.exchange";
    public static final String FANOUT_EXCHANGE = "fanout.exchange";
    public static final String DELAYED_EXCHANGE = "delayed.exchange";
    
    public static final String ORDER_QUEUE = "order.queue";
    public static final String PAYMENT_QUEUE = "payment.queue";
    public static final String DEAD_LETTER_QUEUE = "dead.letter.queue";
    public static final String DELAY_QUEUE = "delay.queue";
    
    public static final String ORDER_ROUTING_KEY = "order.routing.key";
    public static final String PAYMENT_ROUTING_KEY = "payment.routing.key";
    
    // ==================== 消息转换器 ====================
    @Bean
    public MessageConverter jsonMessageConverter(ObjectMapper objectMapper) {
        // 使用JSON序列化
        Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
        converter.setObjectMapper(objectMapper);
        return converter;
    }
    
    // ==================== RabbitTemplate配置 ====================
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory,
                                         MessageConverter messageConverter) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(messageConverter);
        
        // 消息发送确认回调
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.println("消息发送成功: " + correlationData);
            } else {
                System.out.println("消息发送失败: " + cause);
            }
        });
        
        // 消息返回回调(路由失败时触发)
        rabbitTemplate.setReturnsCallback(returned -> {
            System.out.println("消息被退回: " + returned.getMessage());
            System.out.println("退回码: " + returned.getReplyCode());
            System.out.println("退回原因: " + returned.getReplyText());
            System.out.println("交换机: " + returned.getExchange());
            System.out.println("路由键: " + returned.getRoutingKey());
        });
        
        // 设置强制路由
        rabbitTemplate.setMandatory(true);
        
        return rabbitTemplate;
    }
    
    // ==================== RabbitAdmin配置 ====================
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        RabbitAdmin admin = new RabbitAdmin(connectionFactory);
        admin.setAutoStartup(true);  // 自动声明队列和交换机
        return admin;
    }
    
    // ==================== 监听器容器工厂配置 ====================
    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
            ConnectionFactory connectionFactory,
            MessageConverter messageConverter) {
        SimpleRabbitListenerContainerFactory factory = 
            new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        factory.setMessageConverter(messageConverter);
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);  // 手动确认
        factory.setPrefetchCount(10);  // 预取数量
        factory.setConcurrentConsumers(5);  // 并发消费者
        factory.setMaxConcurrentConsumers(10);  // 最大并发消费者
        
        // 设置消费者异常处理器
        factory.setErrorHandler(t -> {
            System.err.println("消费消息异常: " + t.getMessage());
        });
        
        // 设置消息监听器异常处理器
        factory.setDefaultRequeueRejected(false);  // 不重新入队
        
        return factory;
    }
    
    // ==================== 声明队列 ====================
    @Bean
    public Queue orderQueue() {
        // 普通队列
        return QueueBuilder.durable(ORDER_QUEUE)  // 持久化
                .withArgument("x-queue-type", "classic")  // 队列类型
                .build();
    }
    
    @Bean
    public Queue paymentQueue() {
        // 带死信队列的配置
        return QueueBuilder.durable(PAYMENT_QUEUE)
                .withArgument("x-dead-letter-exchange", "")  // 死信交换机
                .withArgument("x-dead-letter-routing-key", DEAD_LETTER_QUEUE)  // 死信路由键
                .withArgument("x-message-ttl", 60000)  // 消息TTL(ms)
                .withArgument("x-max-length", 1000)  // 队列最大长度
                .withArgument("x-overflow", "reject-publish")  // 溢出策略
                .build();
    }
    
    @Bean
    public Queue deadLetterQueue() {
        return QueueBuilder.durable(DEAD_LETTER_QUEUE).build();
    }
    
    @Bean
    public Queue delayQueue() {
        // 延迟队列(需要插件rabbitmq_delayed_message_exchange)
        return QueueBuilder.durable(DELAY_QUEUE).build();
    }
    
    // ==================== 声明交换机 ====================
    @Bean
    public DirectExchange directExchange() {
        return ExchangeBuilder.directExchange(DIRECT_EXCHANGE)
                .durable(true)  // 持久化
                .build();
    }
    
    @Bean
    public TopicExchange topicExchange() {
        return ExchangeBuilder.topicExchange(TOPIC_EXCHANGE)
                .durable(true)
                .build();
    }
    
    @Bean
    public FanoutExchange fanoutExchange() {
        return ExchangeBuilder.fanoutExchange(FANOUT_EXCHANGE)
                .durable(true)
                .build();
    }
    
    @Bean
    public CustomExchange delayedExchange() {
        // 延迟交换机(需要插件支持)
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(DELAYED_EXCHANGE, "x-delayed-message", true, false, args);
    }
    
    // ==================== 绑定队列和交换机 ====================
    @Bean
    public Binding orderBinding() {
        return BindingBuilder.bind(orderQueue())
                .to(directExchange())
                .with(ORDER_ROUTING_KEY);
    }
    
    @Bean
    public Binding paymentBinding() {
        return BindingBuilder.bind(paymentQueue())
                .to(topicExchange())
                .with(PAYMENT_ROUTING_KEY);
    }
    
    @Bean
    public Binding delayBinding() {
        return BindingBuilder.bind(delayQueue())
                .to(delayedExchange())
                .with("delay.routing.key")
                .noargs();
    }
}

四、生产者配置

java 复制代码
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.MessageDeliveryMode;
import java.util.UUID;

@Component
public class RabbitMQProducer {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    /**
     * 发送普通消息
     */
    public void sendMessage(String exchange, String routingKey, Object message) {
        // 设置消息ID
        String messageId = UUID.randomUUID().toString();
        
        rabbitTemplate.convertAndSend(exchange, routingKey, message, m -> {
            // 设置消息属性
            m.getMessageProperties().setMessageId(messageId);
            m.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT); // 持久化
            m.getMessageProperties().setPriority(1); // 优先级
            m.getMessageProperties().setContentEncoding("UTF-8");
            m.getMessageProperties().setContentType("application/json");
            return m;
        });
    }
    
    /**
     * 发送延迟消息(需要插件支持)
     */
    public void sendDelayedMessage(String exchange, String routingKey, 
                                   Object message, int delayMillis) {
        rabbitTemplate.convertAndSend(exchange, routingKey, message, m -> {
            m.getMessageProperties().setDelay(delayMillis);
            return m;
        });
    }
    
    /**
     * 发送确认消息(使用CorrelationData)
     */
    public void sendConfirmMessage(String exchange, String routingKey, 
                                   Object message) {
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        correlationData.getFuture().addCallback(
            result -> {
                if (result.isAck()) {
                    System.out.println("消息确认成功: " + correlationData.getId());
                } else {
                    System.out.println("消息确认失败: " + correlationData.getId());
                }
            },
            ex -> {
                System.out.println("发送异常: " + ex.getMessage());
            }
        );
        
        rabbitTemplate.convertAndSend(exchange, routingKey, message, correlationData);
    }
}

五、消费者配置

java 复制代码
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import com.rabbitmq.client.Channel;
import java.io.IOException;

@Component
public class RabbitMQConsumer {
    
    /**
     * 使用注解监听队列
     * @RabbitListener: 声明监听器
     * @QueueBinding: 绑定队列和交换机
     */
    @RabbitListener(
        bindings = @QueueBinding(
            value = @Queue(value = "order.queue", durable = "true"),
            exchange = @Exchange(value = "direct.exchange", type = ExchangeTypes.DIRECT),
            key = "order.routing.key"
        ),
        concurrency = "5-10"  // 并发配置
    )
    public void handleOrderMessage(Order order, 
                                   Channel channel,
                                   @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
        try {
            // 业务处理逻辑
            System.out.println("收到订单消息: " + order);
            
            // 手动确认消息
            channel.basicAck(deliveryTag, false);
            
            // 拒绝消息(重新入队)
            // channel.basicReject(deliveryTag, true);
            
            // 拒绝消息(不重新入队)
            // channel.basicReject(deliveryTag, false);
            
            // 批量确认
            // channel.basicAck(deliveryTag, true);
            
        } catch (Exception e) {
            // 处理失败,重新入队
            channel.basicReject(deliveryTag, true);
            
            // 或放入死信队列
            // channel.basicReject(deliveryTag, false);
        }
    }
    
    /**
     * 死信队列消费者
     */
    @RabbitListener(queues = "dead.letter.queue")
    public void handleDeadLetterMessage(Message message, Channel channel) throws IOException {
        System.out.println("收到死信消息: " + new String(message.getBody()));
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
    
    /**
     * 延迟队列消费者
     */
    @RabbitListener(queues = "delay.queue")
    public void handleDelayMessage(Message message, Channel channel) throws IOException {
        System.out.println("收到延迟消息: " + new String(message.getBody()));
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}

// 消息实体类
class Order {
    private String orderId;
    private String productName;
    private Double amount;
    // getter/setter省略
}

六、事务配置

java 复制代码
import org.springframework.amqp.rabbit.transaction.RabbitTransactionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
public class TransactionConfig {
    
    /**
     * RabbitMQ 事务管理器
     */
    @Bean
    public RabbitTransactionManager rabbitTransactionManager(
            ConnectionFactory connectionFactory) {
        return new RabbitTransactionManager(connectionFactory);
    }
}

// 使用事务
@Component
class TransactionalService {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Transactional
    public void processWithTransaction(Order order) {
        // 1. 保存到数据库
        // orderRepository.save(order);
        
        // 2. 发送消息(如果在事务中,会在事务提交后发送)
        rabbitTemplate.convertAndSend("exchange", "routingKey", order);
        
        // 如果发生异常,消息不会被发送
        // throw new RuntimeException("模拟异常");
    }
}

七、监控和健康检查配置

java 复制代码
management:
  endpoints:
    web:
      exposure:
        include: health,metrics,rabbitmq
  endpoint:
    health:
      show-details: always

spring:
  rabbitmq:
    # 启用健康检查
    metrics:
      enabled: true
    # 收集消息统计
    collect-message-history: true

八、常见配置问题解决方案

  1. 连接断开重连
yaml 复制代码
spring:
  rabbitmq:
    connection-timeout: 60000
    requested-heartbeat: 60
    retry:
      enabled: true
      max-attempts: 3
  1. 消费者堆积处理
java 复制代码
@Bean
public SimpleRabbitListenerContainerFactory containerFactory(
        ConnectionFactory connectionFactory) {
    SimpleRabbitListenerContainerFactory factory = 
        new SimpleRabbitListenerContainerFactory();
    factory.setConnectionFactory(connectionFactory);
    factory.setPrefetchCount(100);  // 增大预取值
    factory.setConcurrentConsumers(20);  // 增加并发消费者
    factory.setMaxConcurrentConsumers(50);
    return factory;
}
  1. 消息序列化配置
java 复制代码
@Bean
public MessageConverter messageConverter() {
    // 设置全局消息转换器
    Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
    DefaultJackson2JavaTypeMapper typeMapper = new DefaultJackson2JavaTypeMapper();
    typeMapper.setTrustedPackages("com.example.entity.*");
    converter.setJavaTypeMapper(typeMapper);
    return converter;
}

九、最佳实践总结

生产环境必须配置:

  1. 持久化队列和消息
  2. 手动确认模式
  3. 死信队列处理
  4. 合理的重试机制

性能优化:

  1. 适当调整预取值(prefetch)
  2. 合理设置并发消费者数
  3. 使用连接池
  4. 批量确认消息

高可用:

  1. 配置集群连接
  2. 启用镜像队列
  3. 设置合理的TTL和死信队列

监控:

  1. 开启RabbitMQ管理插件
  2. 集成Spring Boot Actuator
  3. 配置告警机制
相关推荐
Zzzzzxl_1 小时前
互联网大厂Java/Agent面试实战:微服务、RAG与Agent化实战(含答疑解析)
java·jvm·spring boot·agent·milvus·rag·microservices
kong@react1 小时前
springbpoot项目,富文本,xss脚本攻击防护,jsoup
java·前端·spring boot·xss
Zzzzzxl_1 小时前
互联网大厂Java/Agent面试实战:Spring Boot、JVM、微服务、Kafka与AI Agent场景问答
java·jvm·spring boot·redis·ai·kafka·microservices
脸大是真的好~1 小时前
尚硅谷-消息队列-rabbitMQ
分布式·rabbitmq
sg_knight7 小时前
Spring 框架中的 SseEmitter 使用详解
java·spring boot·后端·spring·spring cloud·sse·sseemitter
Dolphin_Home10 小时前
笔记:SpringBoot静态类调用Bean的2种方案(小白友好版)
java·spring boot·笔记
刘一说11 小时前
Nacos 权限控制详解:从开源版 v2.2+ 到企业级安全实践
spring boot·安全·spring cloud·微服务·nacos·架构·开源
Q_Q51100828512 小时前
python+django/flask+vue的大健康养老公寓管理系统
spring boot·python·django·flask·node.js
czlczl2002092512 小时前
通过哪些条件确定用哪个消息转换器
spring boot