RabbitMQ:系统学习笔记

概述

RabbitMQ是一个开源的消息队列系统,实现了高级消息队列协议(AMQP)。它提供了强大的消息传递功能,支持多种消息传递模式,是分布式系统中常用的消息中间件。

本文将详细介绍RabbitMQ的核心概念、工作原理、安装配置以及在Java应用中的使用方法。

RabbitMQ核心概念

消息中间件

消息中间件是分布式系统中重要的组件,用于:

解耦:生产者和消费者之间不需要直接通信

异步:提高系统的响应性和吞吐量

削峰:缓冲瞬时高并发请求

可靠:确保消息不丢失

基本概念

Producer(生产者):发送消息的应用程序

Consumer(消费者):接收消息的应用程序

Queue(队列):存储消息的缓冲区

Exchange(交换机):接收生产者发送的消息,根据路由规则将消息转发到队列

Binding(绑定):交换机和队列之间的连接关系

Routing Key(路由键):消息发送时指定的路由信息

Connection(连接):应用程序与RabbitMQ服务器之间的TCP连接

Channel(通道):建立在连接之上的虚拟连接

安装和配置

Docker安装

java 复制代码
# 拉取RabbitMQ镜像
docker pull rabbitmq:management

# 运行RabbitMQ容器
docker run -d \
  --name rabbitmq \
  -p 5672:5672 \
  -p 15672:15672 \
  -e RABBITMQ_DEFAULT_USER=admin \
  -e RABBITMQ_DEFAULT_PASS=admin123 \
  rabbitmq:management

# 查看容器状态
docker ps

# 查看日志
docker logs rabbitmq
访问管理界面
打开浏览器访问:http://localhost:15672


用户名:admin
密码:admin123

工作模式

1. 简单模式(Simple)

一个生产者对应一个消费者,最简单的消息传递模式。

生产者代码:

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public Queue simpleQueue() {
        returnnew Queue("simple.queue", true);
    }
}

@Service
publicclass SimpleProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String message) {
        rabbitTemplate.convertAndSend("simple.queue", message);
        System.out.println("发送消息:" + message);
    }
}

消费者代码:

java 复制代码
@Component
@RabbitListener(queues = "simple.queue")
public class SimpleConsumer {

    @RabbitHandler
    public void receiveMessage(String message) {
        System.out.println("接收消息:" + message);
        // 处理消息逻辑
    }
}

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

一个生产者对应多个消费者,消费者竞争消费消息,实现负载均衡。

生产者代码:

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public Queue workQueue() {
        returnnew Queue("work.queue", true);
    }
}

@Service
publicclass WorkProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String message) {
        rabbitTemplate.convertAndSend("work.queue", message);
        System.out.println("发送消息:" + message);
    }
}

消费者代码:

java 复制代码
@Component
publicclass WorkConsumer1 {

    @RabbitListener(queues = "work.queue")
    public void receiveMessage(String message) {
        System.out.println("消费者1接收消息:" + message);
        try {
            // 模拟处理时间
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("消费者1处理完成:" + message);
    }
}

@Component
publicclass WorkConsumer2 {

    @RabbitListener(queues = "work.queue")
    public void receiveMessage(String message) {
        System.out.println("消费者2接收消息:" + message);
        try {
            // 模拟处理时间
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("消费者2处理完成:" + message);
    }
}

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

一个生产者发送消息,通过交换机广播给多个队列,多个消费者分别处理。

配置代码:

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public FanoutExchange fanoutExchange() {
        returnnew FanoutExchange("fanout.exchange");
    }

    @Bean
    public Queue fanoutQueue1() {
        returnnew Queue("fanout.queue1", true);
    }

    @Bean
    public Queue fanoutQueue2() {
        returnnew Queue("fanout.queue2", true);
    }

    @Bean
    public Binding binding1(FanoutExchange fanoutExchange, Queue fanoutQueue1) {
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }

    @Bean
    public Binding binding2(FanoutExchange fanoutExchange, Queue fanoutQueue2) {
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }
}

生产者代码:

java 复制代码
@Service
public class FanoutProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String message) {
        rabbitTemplate.convertAndSend("fanout.exchange", "", message);
        System.out.println("发布消息:" + message);
    }
}

消费者代码:

java 复制代码
@Component
@RabbitListener(queues = "fanout.queue1")
publicclass FanoutConsumer1 {

    @RabbitHandler
    public void receiveMessage(String message) {
        System.out.println("消费者1接收消息:" + message);
    }
}

@Component
@RabbitListener(queues = "fanout.queue2")
publicclass FanoutConsumer2 {

    @RabbitHandler
    public void receiveMessage(String message) {
        System.out.println("消费者2接收消息:" + message);
    }
}

4. 路由模式(Routing)

根据路由键将消息发送到指定的队列。

配置代码:

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public DirectExchange directExchange() {
        returnnew DirectExchange("direct.exchange");
    }

    @Bean
    public Queue directQueue1() {
        returnnew Queue("direct.queue1", true);
    }

    @Bean
    public Queue directQueue2() {
        returnnew Queue("direct.queue2", true);
    }

    @Bean
    public Binding bindingDirect1(DirectExchange directExchange, Queue directQueue1) {
        return BindingBuilder.bind(directQueue1).to(directExchange).with("info");
    }

    @Bean
    public Binding bindingDirect2(DirectExchange directExchange, Queue directQueue2) {
        return BindingBuilder.bind(directQueue2).to(directExchange).with("error");
    }
}

生产者代码:

java 复制代码
@Service
publicclass DirectProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendInfoMessage(String message) {
        rabbitTemplate.convertAndSend("direct.exchange", "info", "INFO: " + message);
        System.out.println("发送INFO消息:" + message);
    }

    public void sendErrorMessage(String message) {
        rabbitTemplate.convertAndSend("direct.exchange", "error", "ERROR: " + message);
        System.out.println("发送ERROR消息:" + message);
    }
}

消费者代码:

java 复制代码
@Component
@RabbitListener(queues = "direct.queue1")
publicclass DirectConsumer1 {

    @RabbitHandler
    public void receiveMessage(String message) {
        System.out.println("INFO消费者接收消息:" + message);
    }
}

@Component
@RabbitListener(queues = "direct.queue2")
publicclass DirectConsumer2 {

    @RabbitHandler
    public void receiveMessage(String message) {
        System.out.println("ERROR消费者接收消息:" + message);
    }
}

5. 主题模式(Topic)

根据通配符匹配的路由键将消息发送到相应的队列。

配置代码:

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public TopicExchange topicExchange() {
        returnnew TopicExchange("topic.exchange");
    }

    @Bean
    public Queue topicQueue1() {
        returnnew Queue("topic.queue1", true);
    }

    @Bean
    public Queue topicQueue2() {
        returnnew Queue("topic.queue2", true);
    }

    @Bean
    public Binding bindingTopic1(TopicExchange topicExchange, Queue topicQueue1) {
        return BindingBuilder.bind(topicQueue1).to(topicExchange).with("user.*");
    }

    @Bean
    public Binding bindingTopic2(TopicExchange topicExchange, Queue topicQueue2) {
        return BindingBuilder.bind(topicQueue2).to(topicExchange).with("user.#");
    }
}

生产者代码:

java 复制代码
@Service
publicclass TopicProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendUserCreateMessage(String message) {
        rabbitTemplate.convertAndSend("topic.exchange", "user.create", "创建用户:" + message);
        System.out.println("发送用户创建消息:" + message);
    }

    public void sendUserUpdateMessage(String message) {
        rabbitTemplate.convertAndSend("topic.exchange", "user.update", "更新用户:" + message);
        System.out.println("发送用户更新消息:" + message);
    }

    public void sendUserDeleteMessage(String message) {
        rabbitTemplate.convertAndSend("topic.exchange", "user.delete", "删除用户:" + message);
        System.out.println("发送用户删除消息:" + message);
    }
}

消费者代码:

java 复制代码
@Component
@RabbitListener(queues = "topic.queue1")
publicclass TopicConsumer1 {

    @RabbitHandler
    public void receiveMessage(String message) {
        System.out.println("用户操作消费者1接收消息:" + message);
    }
}

@Component
@RabbitListener(queues = "topic.queue2")
publicclass TopicConsumer2 {

    @RabbitHandler
    public void receiveMessage(String message) {
        System.out.println("用户操作消费者2接收消息:" + message);
    }
}

高级特性

消息确认机制

生产者确认:

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);

        // 启用发布者确认
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.println("消息发送成功:" + correlationData.getId());
            } else {
                System.out.println("消息发送失败:" + cause);
            }
        });

        // 启用发布者返回
        rabbitTemplate.setReturnsCallback(returned -> {
            System.out.println("消息无法路由:" + returned.getMessage());
        });

        return rabbitTemplate;
    }
}

消费者确认:

@Component

java 复制代码
@RabbitListener(queues = "confirm.queue")
publicclass ConfirmConsumer {

    @RabbitHandler
    public void receiveMessage(String message, Channel channel, Message msg) throws IOException {
        try {
            System.out.println("接收消息:" + message);
            // 处理消息逻辑

            // 手动确认消息
            channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            // 处理失败,拒绝消息并重新入队
            channel.basicNack(msg.getMessageProperties().getDeliveryTag(), false, true);
        }
    }
}

死信队列

处理无法被正常消费的消息。

配置代码:

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public Queue normalQueue() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange", "dead.letter.exchange");
        args.put("x-dead-letter-routing-key", "dead.letter");
        args.put("x-message-ttl", 60000); // 消息TTL 60秒
        returnnew Queue("normal.queue", true, false, false, args);
    }

    @Bean
    public Queue deadLetterQueue() {
        returnnew Queue("dead.letter.queue", true);
    }

    @Bean
    public DirectExchange deadLetterExchange() {
        returnnew DirectExchange("dead.letter.exchange");
    }

    @Bean
    public Binding deadLetterBinding(DirectExchange deadLetterExchange, Queue deadLetterQueue) {
        return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with("dead.letter");
    }
}

死信消费者:

java 复制代码
@Component
@RabbitListener(queues = "dead.letter.queue")
public class DeadLetterConsumer {

    @RabbitHandler
    public void receiveMessage(String message) {
        System.out.println("处理死信消息:" + message);
        // 处理死信消息的逻辑
    }
}

消息持久化

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public Queue durableQueue() {
        // durable=true 表示队列持久化
        returnnew Queue("durable.queue", true);
    }

    @Bean
    public Exchange durableExchange() {
        // durable=true 表示交换机持久化
        returnnew DirectExchange("durable.exchange", true, false);
    }
}

@Service
publicclass DurableProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(String message) {
        // MessageProperties 设置消息持久化
        MessageProperties properties = new MessageProperties();
        properties.setDeliveryMode(MessageDeliveryMode.PERSISTENT);

        Message msg = new Message(message.getBytes(), properties);
        rabbitTemplate.send("durable.exchange", "durable.key", msg);
    }
}

监控和管理

管理界面功能

RabbitMQ管理界面提供了丰富的监控和管理功能:

Overview:查看整体状态和统计信息

Connections:查看连接信息

Channels:查看通道信息

Exchanges:管理交换机

Queues:管理队列

Admin:用户和权限管理

常用监控命令

java 复制代码
# 查看队列信息
rabbitmqctl list_queues name messages consumers

# 查看交换机信息
rabbitmqctl list_exchanges

# 查看绑定关系
rabbitmqctl list_bindings

# 查看连接信息
rabbitmqctl list_connections

Spring Boot Actuator集成

java 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

management:
  endpoints:
    web:
      exposure:
        include: health,info,rabbit
  endpoint:
    rabbit:
      enabled: true

性能优化

1. 连接复用

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setHost("localhost");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin123");

        // 设置连接缓存
        connectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CONNECTION);
        connectionFactory.setConnectionCacheSize(10);

        // 设置通道缓存
        connectionFactory.setChannelCacheSize(25);

        return connectionFactory;
    }
}

2. 批量发送

java 复制代码
@Service
publicclass BatchProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendBatchMessages(List<String> messages) {
        List<Message> messageList = messages.stream()
                .map(msg -> MessageBuilder.withBody(msg.getBytes()).build())
                .collect(Collectors.toList());

        // 批量发送消息
        for (Message message : messageList) {
            rabbitTemplate.send("batch.exchange", "batch.routing.key", message);
        }
    }
}

3. 消费者优化

java 复制代码
@Configuration
publicclass RabbitConfig {

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);

        // 设置消费者并发数
        factory.setConcurrentConsumers(3);
        factory.setMaxConcurrentConsumers(10);

        // 设置预取数量
        factory.setPrefetchCount(5);

        // 设置手动确认
        factory.setAcknowledgeMode(AcknowledgeMode.MANUAL);

        return factory;
    }
}

故障排查

常见问题
消息丢失

检查队列和消息是否持久化

确认生产者和消费者确认机制是否正确配置

消息重复消费

确保消费者处理逻辑的幂等性

使用消息ID进行去重

连接断开

检查网络连接稳定性

配置连接重试机制

性能问题

监控队列长度和消费者数量

调整预取数量和并发消费者数

日志配置

java 复制代码
<dependency>
    <groupId>org.springframework.amqp</groupId>
    <artifactId>spring-rabbit</artifactId>
</dependency>
logging:
  level:
    com.rabbitmq: DEBUG
    org.springframework.amqp: DEBUG

最佳实践

1. 消息设计

消息体保持简洁,包含必要信息

使用JSON格式,便于解析

添加消息ID和时间戳,便于追踪

2. 错误处理

实现全局异常处理器

配置死信队列处理失败消息

记录详细的错误日志

3. 监控告警

监控队列长度和消息积压

设置合理的告警阈值

定期清理过期消息

4. 安全配置

使用强密码和加密连接

配置访问控制和权限管理

定期更新和维护

5. 高可用部署

配置集群模式

设置镜像队列

实现负载均衡

总结

通过本文的学习,你已经掌握了:

RabbitMQ的核心概念和架构原理

五种常用的消息传递模式及其实现

高级特性如消息确认、死信队列、持久化

监控管理和性能优化技巧

故障排查和最佳实践

RabbitMQ作为企业级的消息中间件,在微服务架构、异步处理、系统解耦等方面发挥着重要作用。合理使用RabbitMQ可以显著提升系统的可扩展性、可靠性和性能。

相关推荐
YJlio2 小时前
进程和诊断工具速查手册(8.13):VMMap / DebugView / LiveKd / Handle / ListDLLs 一页式现场排障清单
数据库·笔记·学习
alwaysuzybaiyy3 小时前
物联网控制|计算机控制-刘川来胡乃平版|第4章:过程通道与人机接口-4.4Human-Machine Interface|课堂笔记|
笔记·物联网·powerpoint
q***72194 小时前
Spring Boot 中 RabbitMQ 的使用
spring boot·rabbitmq·java-rabbitmq
青衫码上行4 小时前
【Java Web学习 | 第12篇】JavaScript(6)DOM
java·开发语言·前端·javascript·学习
弘毅 失败的 mian4 小时前
C++、Java 还是测试开发?
java·c++·经验分享·笔记·测试开发·技术方向·就业
YangYang9YangYan4 小时前
中专生学历提升与职业发展指南
大数据·人工智能·学习·数据分析
喝养乐多长不高4 小时前
Rabbit MQ:概述
java·rabbitmq·mq·amqp
深蓝海拓4 小时前
YOLO v11的学习记录(五) 使用自定义数据从头训练一个实例分割的模型
学习·yolo
Gary Studio4 小时前
鋰電池充電芯片學習
学习