RabbitMQ(Java快速入门附Demo代码)

小巫Demo程序日记:RabbitMQ快速入门


RabbitMQ 核心逻辑架构图

RabbitMQ 是一个消息队列系统,其核心架构由以下几个关键组件组成:

  • 生产者(Producer):发送消息的应用。
  • 交换机(Exchange):接收生产者发送的消息,并根据路由规则将消息分发到队列。
  • 队列(Queue):存储消息的地方,消费者从队列中获取消息。
  • 消费者(Consumer):接收并处理消息的应用。
  • 绑定(Binding):交换机和队列之间的关联,定义了消息的路由规则。

以下是 RabbitMQ 核心逻辑的架构图(使用 Mermaid 语法表示):

发送消息
路由
路由
接收消息
接收消息
Producer
Exchange
队列 1
队列 2
消费者 1
消费者 2

在这个架构中:

  1. 生产者将消息发送到交换机。
  2. 交换机根据绑定规则(例如 routing key)将消息路由到对应的队列。
  3. 消费者从队列中接收并处理消息。

比如周杰伦演唱会场景类比

为了让 RabbitMQ 的工作原理更易于理解,我们将其与演唱会场景进行类比:

  • 生产者(Producer):演唱会组织者,负责发布演唱会信息。
  • 交换机(Exchange):演唱会信息发布平台,负责将信息分发到不同的渠道。
  • 队列(Queue):不同的信息渠道,例如社交媒体、官方网站、电子邮件等。
  • 消费者(Consumer):粉丝或观众,通过自己关注的渠道接收演唱会信息。
  • 绑定(Binding):定义了信息发布平台如何将信息分发到不同的渠道。

在这个类比中:

  • 演唱会组织者(生产者)通过信息发布平台(交换机)发送演唱会信息,例如“演唱会日期、地点、票价”。
  • 发布平台根据绑定规则将信息路由到不同的渠道(队列),比如社交媒体或电子邮件。
  • 粉丝(消费者)从自己订阅的渠道(队列)接收信息。

Demo(Java 版)

下面是一个使用 Java 和 RabbitMQ 客户端库的 Demo,模拟演唱会信息发布的场景。我们将使用 Direct Exchange 类型,因为它允许根据 routing key 精确匹配队列。

Demo 场景
  • Exchange:演唱会信息发布平台(命名为 concert_exchange)。
  • Queue:社交媒体渠道(命名为 social_media_queue)。
  • Binding:将发布平台与社交媒体渠道绑定,routing key 为 "social_media"
  • Producer:组织者发送演唱会信息到发布平台,routing key 为 "social_media"
  • Consumer:粉丝从社交媒体渠道接收信息。
1. 前提条件
  • 确保 RabbitMQ 服务已安装并运行(默认运行在 localhost:5672)。
  • 在 Java 项目中添加 RabbitMQ 客户端库依赖(以 Maven 为例):
<dependency>
    <groupId>com.rabbitmqgroupId>
    <artifactId>amqp-clientartifactId>
    <version>5.14.0version>
dependency>
2. 生产者代码(ConcertProducer.java)

生产者发送一条演唱会信息到交换机。

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class ConcertProducer {
    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost"); // RabbitMQ 服务器地址
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            String exchangeName = "concert_exchange";
            channel.exchangeDeclare(exchangeName, "direct"); // 声明 Direct Exchange
            String queueName = "social_media_queue";
            channel.queueDeclare(queueName, false, false, false, null); // 声明队列
            String routingKey = "social_media";
            channel.queueBind(queueName, exchangeName, routingKey); // 绑定队列和交换机

            String message = "演唱会信息:2023年12月1日,北京,票价500元";
            channel.basicPublish(exchangeName, routingKey, null, message.getBytes());
            System.out.println("消息已发送: " + message);
        }
    }
}
3. 消费者代码(ConcertConsumer.java)

消费者从队列中接收消息并打印。

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class ConcertConsumer {
    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost"); // RabbitMQ 服务器地址
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        String queueName = "social_media_queue";
        channel.queueDeclare(queueName, false, false, false, null); // 声明队列

        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println("收到消息: " + message);
        };
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});
        System.out.println("等待接收消息...");
    }
}
4. 运行 Demo
  1. 启动 RabbitMQ 服务(如果尚未运行)。
  2. 运行 ConcertConsumer.java,等待接收消息。
  3. 运行 ConcertProducer.java,发送消息。

运行后,你会在消费者端看到类似以下输出:

等待接收消息...
收到消息: 演唱会信息:2023年12月1日,北京,票价500元

生产者端输出:

消息已发送: 演唱会信息:2023年12月1日,北京,票价500元

1. 注释后的 Demo 代码

1.1 生产者代码(ConcertProducer.java)
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public class ConcertProducer {
    public static void main(String[] args) throws Exception {
        // 创建连接工厂,用于配置与 RabbitMQ 服务器的连接
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost"); // 设置 RabbitMQ 服务器地址,默认端口 5672

        // 使用 try-with-resources 建立连接和通道,确保资源自动关闭
        try (Connection connection = factory.newConnection(); // 创建与 RabbitMQ 的连接
             Channel channel = connection.createChannel()) {   // 创建通道,用于发送消息

            // 声明交换机(Exchange),类型为 Direct,用于精确路由消息
            String exchangeName = "concert_exchange";
            channel.exchangeDeclare(exchangeName, "direct");

            // 声明队列(Queue),用于存储消息
            String queueName = "social_media_queue";
            channel.queueDeclare(queueName, false, false, false, null);
            // 参数说明:
            // - queueName: 队列名称
            // - durable: false 表示队列非持久化,重启后丢失
            // - exclusive: false 表示队列不专属于某个连接
            // - autoDelete: false 表示队列不自动删除
            // - arguments: null 表示无额外参数

            // 将队列绑定到交换机,指定 routing key
            String routingKey = "social_media";
            channel.queueBind(queueName, exchangeName, routingKey);
            // 绑定确保消息根据 routing key 路由到指定队列

            // 发送消息到交换机
            String message = "演唱会信息:2023年12月1日,北京,票价500元";
            channel.basicPublish(exchangeName, routingKey, null, message.getBytes());
            // 参数说明:
            // - exchangeName: 目标交换机
            // - routingKey: 路由键,用于匹配绑定
            // - props: null 表示无额外消息属性
            // - body: 消息内容,转换为字节数组

            System.out.println("消息已发送: " + message); // 打印确认消息已发送
        }
    }
}
1.2 消费者代码(ConcertConsumer.java)
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

public class ConcertConsumer {
    public static void main(String[] args) throws Exception {
        // 创建连接工厂,用于配置与 RabbitMQ 服务器的连接
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost"); // 设置 RabbitMQ 服务器地址,默认端口 5672

        // 建立连接和通道
        Connection connection = factory.newConnection(); // 创建与 RabbitMQ 的连接
        Channel channel = connection.createChannel();    // 创建通道,用于接收消息

        // 声明队列(Queue),确保队列存在
        String queueName = "social_media_queue";
        channel.queueDeclare(queueName, false, false, false, null);
        // 参数与生产者一致,确保队列配置相同

        // 定义消息接收回调,处理接收到的消息
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8"); // 将消息字节转换为字符串
            System.out.println("收到消息: " + message);              // 打印接收到的消息
        };

        // 订阅队列,设置自动确认消息
        channel.basicConsume(queueName, true, deliverCallback, consumerTag -> {});
        // 参数说明:
        // - queueName: 订阅的队列名称
        // - autoAck: true 表示自动确认消息,收到后立即从队列移除
        // - deliverCallback: 消息到达时的处理逻辑
        // - cancelCallback: 消费者取消时的回调(此处为空实现)

        System.out.println("等待接收消息..."); // 提示消费者已就绪
    }
}

2. 处理逻辑图

以下是生产者和消费者之间消息传递的逻辑图,RabbitMQ 的核心流程:

Producer Exchange Queue Consumer 发送消息(routing key = "social_media") 路由消息到 social_media_queue 订阅队列 传递消息 处理消息(打印) Producer Exchange Queue Consumer

逻辑图说明

  1. 生产者(Producer) 发送消息到 交换机(Exchange),并指定 routing key 为 "social_media"
  2. 交换机 根据 routing key 将消息路由到绑定的 队列(Queue)social_media_queue)。
  3. 消费者(Consumer) 订阅队列,等待消息到达。
  4. 队列 将消息传递给 消费者
  5. 消费者 处理消息(在本例中,打印消息内容)。

3. 演唱会场景类比

为了让 RabbitMQ 的工作原理更直观,我们将其与演唱会场景进行类比:

  • 生产者(Producer):演唱会组织者,发布演唱会信息。
  • 交换机(Exchange):信息发布平台,根据渠道类型分发信息。
  • 队列(Queue):社交媒体渠道,存储待发布的信息。
  • 消费者(Consumer):粉丝,通过社交媒体接收信息。
  • 绑定(Binding):定义了信息如何从发布平台路由到社交媒体渠道。

类比流程

  • 组织者(生产者)通过发布平台(交换机)发送信息,例如“2023年12月1日,北京,票价500元”。
  • 发布平台根据渠道类型(routing key)将信息路由到社交媒体(队列)。
  • 粉丝(消费者)从社交媒体渠道接收并查看信息。

4. 总结

通过注释后的代码、逻辑图和演唱会场景类比,我们详细展示了 RabbitMQ 的核心工作流程:

  • 生产者 通过 交换机 发送消息。
  • 交换机 根据 路由规则 将消息分发到 队列
  • 消费者 从队列中接收并处理消息。

这个 Demo 不仅通过代码实现了消息传递,还借助逻辑图和类比帮助您更直观地理解 RabbitMQ 的机制。希望这对您掌握 RabbitMQ 有所帮助!

你可能感兴趣的:(RabbitMQ,java-rabbitmq,rabbitmq,java)