Java研学-RabbitMQ(三)

一 消息通信协议

1 AMQP

AMQP 是一个开放的、跨语言、跨平台的消息协议标准,用于在分布式系统中传递业务消息。它定义了消息队列的二进制协议格式和交互模型(如交换机、队列、绑定等),确保不同语言(Java、Python、C#等)和平台(RabbitMQ、Qpid等)的实现能够互操作。

2 Spring AMQP

Spring AMQP 是 Spring 框架对 AMQP 协议(如 RabbitMQ)的抽象与封装,提供了一套简洁的 Java API 来简化消息的生产和消费。

它通过AmqpTemplate模板类实现消息的快速发送(如自动序列化、路由键设置),结合@RabbitListener注解实现声明式的消费者监听,同时支持动态声明交换机、队列和绑定(通过 RabbitAdmin),并深度集成 Spring 生态(如依赖注入、事务管理)。

其核心优势在于隐藏底层协议细节,让开发者仅需关注业务逻辑,无需手动处理连接、通道或消息确认等复杂操作,从而高效构建异步、解耦的分布式系统。

二 入门demo

1 项目路径图

2 交换机与队列准备

创建虚拟主机/midhuang,使用其中的交换机amq.fanout,与队列xiaohuang.queue1进行绑定。

3 父工程导入依赖

创建spring项目,为父工程导入依赖,两个子工程会会自动继承这些依赖

java 复制代码
        <!-- Lombok:简化Java代码(如自动生成Getter/Setter) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <!-- Spring AMQP + RabbitMQ 集成 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

        <!-- Spring Boot 单元测试 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

4 各个微服务中配置文件

① consumer(消费者),5672是用来发消息的端口,15672是Web控制台

java 复制代码
spring:
  rabbitmq:
    host: 192.168.44.128
    port: 5672 
    virtual-host: /midhuang
    username: dahuang
    password: "dahuang66"
logging:
  level:
    cn.tj.consumer.listeners: DEBUG # 设置为 DEBUG 以查看详细日志

② publisher(生产者)

java 复制代码
spring:
  rabbitmq:
    host: 192.168.44.128
    port: 5672
    virtual-host: /midhuang
    username: dahuang
    password: "dahuang66"
logging:
  level:
    cn.tj.consumer.listeners: DEBUG # 设置为 DEBUG 以查看详细日志

5 测试类发送消息

利用RabbitTemplate发送消息

java 复制代码
@SpringBootTest
class PublisherApplicationTests {
    // 注入 RabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    // 直接发送消息到队列
    @Test
    public void testHuangQueue() {
        // 1. 定义队列名称
        String queueName = ".queue";
        // 2. 定义消息内容
        String message = "hello, spring amqp!";
        // 3. 发送消息(默认路由到队列)
        rabbitTemplate.convertAndSend(queueName, message);
        System.out.println("消息发送成功: " + message);
    }
}

6 控制台检查刚刚发送消息

7 接收消息

利用@RabbitListener注解声明要监听的队列,监听消息,此时消费者服务需启动保持监听状态

java 复制代码
@Slf4j
@Component
public class MqListener {
    @RabbitListener(queues = "xiaohuang.queue1")
    public void listenHuangQueue(String msg) {
        log.info("收到消息: {}", msg);
        // 调试:打印消息长度和字节(如果 msg 为 null,会输出 "null")
        log.debug("消息长度: {}, 内容: {}", msg == null ? "null" : msg.length(), msg);
    }
}

三 Workqueues

Workqueues(工作队列)是一种常见的任务分发模型,将多个消费者绑定到一个队列,共同消费队列中的消息,通过共享队列实现负载均衡,从而解决消息堆积问题。

1 创建队列 work.queue

2 添加两个消费者 -- MqListener

java 复制代码
@Slf4j
@Component
public class MqListener {
    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue1(String msg) {
        log.info("1号消费者收到消息: {}", msg);
    }
    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue2(String msg) {
        log.info("2号消费者收到消息: {}", msg);
    }
}

3 生产者连续发送消息 -- PublisherApplicationTests

java 复制代码
@SpringBootTest
class PublisherApplicationTests {
    // 注入 RabbitTemplate
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void testWorkQueue() throws InterruptedException {
        String queueName = "work.queue";

        // 发送50条测试消息
        for (int i = 1; i <= 40; i++) {
            String msg = "hello" + i;
            rabbitTemplate.convertAndSend(queueName, msg);
            System.out.println(" [x] Sent '" + msg + "'");
            Thread.sleep(30); // 模拟延迟,避免消息爆发
        }
    }
}

4 控制台输出

此时并未考虑到消费者的处理能力,RabbitMQ 默认使用 轮询(Round-Robin) 策略分发消息,这可能导致某些消费者积压大量未处理消息,而其他消费者空闲。

5 编写配置文件 -- consumer

prefetchCount:1像外卖小哥一次只接一单,平台会一次性给小哥派5 个订单(即使他还没处理完之前的订单)。如果小哥手慢(比如堵车),这 5 个订单都会卡在他手里,其他空闲的小哥却没订单可接。

启用prefetchCount:1后:平台每次只给小哥派 1 个订单。小哥必须完成这个订单(送到顾客手里),平台才会派下一个订单。如果小哥 A 处理快,他很快能接下一个订单;小哥 B 处理慢,他手头的订单不会影响别人。

java 复制代码
spring:
  rabbitmq:
    host: 192.168.44.128
    port: 5672
    virtual-host: /midhuang
    username: dahuang
    password: "dahuang66"
    listener:
      simple:
        prefetch: 1
logging:
  level:
    cn.tj.consumer.listeners: DEBUG # 设置为 DEBUG 以查看详细日志

6 设置消费者处理速度 -- MqListener

java 复制代码
@Slf4j
@Component
public class MqListener {
    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue1(String msg) throws InterruptedException {
        log.info("1号消费者收到消息: {}", msg);
        Thread.sleep(20);
    }
    @RabbitListener(queues = "work.queue")
    public void listenWorkQueue2(String msg) throws InterruptedException {
        log.debug("2号消费者收到消息: {}", msg);
        Thread.sleep(200);
    }
}

7 控制台输出

相关推荐
Bro_cat4 分钟前
Java基础
java·开发语言·面试
一起养小猫18 分钟前
《Java数据结构与算法》第三篇(下)队列全解析:从基础概念到高级应用
java·开发语言·数据结构
2501_9411426421 分钟前
人工智能与推荐系统在高并发互联网架构中的优化与工程实践经验分享
rabbitmq
一只会写代码的猫24 分钟前
面向企业级分布式系统的Java微服务架构设计与高性能实践深度探索与经验分享
rabbitmq
vx_vxbs6625 分钟前
【SSM电动车智能充电服务平台】(免费领源码+演示录像)|可做计算机毕设Java、Python、PHP、小程序APP、C#、爬虫大数据、单片机、文案
java·spring boot·mysql·spring cloud·小程序·php·idea
叹隙中驹石中火梦中身30 分钟前
解耦神器Event和EventListener
java
Boop_wu39 分钟前
[Java EE] 多线程进阶(JUC)(2)
java·jvm·算法
小坏讲微服务40 分钟前
SpringCloud整合Scala实现MybatisPlus实现业务增删改查
java·spring·spring cloud·scala·mybatis plus
N***p36541 分钟前
五大消息模型介绍(RabbitMQ 详细注释版)
java·rabbitmq·java-rabbitmq
m***l11544 分钟前
集成RabbitMQ+MQ常用操作
分布式·rabbitmq