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可以显著提升系统的可扩展性、可靠性和性能。

相关推荐
航Hang*4 分钟前
第3章:复习篇——第3节:数据查询与统计---题库
数据库·笔记·sql·学习·mysql·期末·复习
咚咚王者9 分钟前
人工智能之核心基础 机器学习 第十四章 半监督与自监督学习总结归纳
人工智能·学习·机器学习
独自破碎E11 分钟前
说说RabbitMQ的集群模式
rabbitmq
知识分享小能手18 分钟前
Oracle 19c入门学习教程,从入门到精通,Oracle管理工具 —— 知识点详解(3)
数据库·学习·oracle
张祥64228890419 分钟前
线性代数本质笔记七
笔记·线性代数
科技林总20 分钟前
【系统分析师】4.1 计算机网络基础
学习
天天睡大觉28 分钟前
Python学习9
开发语言·python·学习
2301_7973122629 分钟前
学习Java39天
开发语言·python·学习
Reenrr32 分钟前
C++学习
开发语言·c++·学习
望忆38 分钟前
关于《SaviorRec: Semantic-Behavior Alignment for Cold-StartRecommendation》的学习
学习