RabbitMQ速通--02工作模式

RabbitMQ的工作模式

在发送或者接收消息后我们可以在RabbitMQ的控制面板中去查看其发生的变化

对于RabbitMQ的不同工作模式,其本质上是基于不同类型的交换机(Exchange)和不同的绑定(Binding)规则来实现的

以下所有示例都需要导入此依赖,这些示例是使用了原生API,可以更好的帮助我们理解RabbitMQ的工作模式,在实际开发中仍然会使用Spring系列的框架对其进行整合.
我只在第一个示例中给出较为详细的代码,后续工作模式示例只给出核心代码

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
 </dependency>

简单模式

使用的交换机:默认交换机(“”,Direct 类型)

特点:
生产者直接发送消息到队列(实际上是发送到默认交换机,路由键 routing_key 设为队列名)

消费者直接从队列消费

/**
 * 简单模式 - 生产者
 * 特点:一个生产者发送消息到一个队列,一个消费者从该队列接收消息
 */
public class SimpleProducer {
    // 定义队列名称
    private final static String QUEUE_NAME = "hello";
    
    public static void main(String[] args) throws Exception {
        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        // 设置RabbitMQ服务器地址
        factory.setHost("localhost");
        // 设置RabbitMQ服务器端口号
        factory.setPort(5672);
        // 设置虚拟主机地址
        factory.setVirtualHost("/");
        // 设置RabbitMQ服务器用户名和密码
        factory.setUsername("guest");
        factory.setPassword("guest");
        
        // try-with-resources确保资源自动关闭
        try (Connection connection = factory.newConnection(); // 创建连接
             Channel channel = connection.createChannel()) {  // 创建通道
            
            // 声明队列,参数说明:
            // 1. 队列名称
            // 2. 是否持久化(false表示不持久化)
            // 3. 是否独占队列(false表示不独占)
            // 4. 是否自动删除(false表示不自动删除)
            // 5. 其他参数(null表示无其他参数)
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
            
            // 准备发送的消息
            String message = "Hello World!";
            
            // 发布消息,参数说明:
            // 1. 交换机名称(""表示默认交换机)
            // 2. 路由键(这里是队列名称)
            // 3. 消息属性(null表示无特殊属性)
            // 4. 消息体(字节数组)
            channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
            
            System.out.println(" [x] Sent '" + message + "'");
        }
    }
}

/**
 * 简单模式 - 消费者
 */
public class SimpleConsumer {
    private final static String QUEUE_NAME = "hello";
    
    public static void main(String[] args) throws Exception {
        // 创建连接工厂
        ConnectionFactory factory = new ConnectionFactory();
        // 设置RabbitMQ服务器地址
        factory.setHost("localhost");
        // 设置RabbitMQ服务器端口号
        factory.setPort(5672);
        // 设置虚拟主机地址
        factory.setVirtualHost("/");
        // 设置RabbitMQ服务器用户名和密码
        factory.setUsername("guest");
        factory.setPassword("guest");
        
        // 创建连接和通道
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        
        // 声明队列(必须与生产者声明的队列一致)
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
        System.out.println(" [*] Waiting for messages...");
        
        // 定义消息接收回调
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            // 将消息体转换为字符串
            String message = new String(delivery.getBody(), "UTF-8");
            System.out.println(" [x] Received '" + message + "'");
        };
        
        // 开始消费消息,参数说明:
        // 1. 队列名称
        // 2. 是否自动确认(true表示自动确认)
        // 3. 消息接收回调
        // 4. 消费者取消回调(这里为空实现)
        channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {});
    }
}

工作队列模式

使用的交换机:默认交换机(“”,Direct 类型)

特点:
多个消费者共享同一个队列,RabbitMQ 以轮询(Round-Robin)方式分发消息

适合任务分发场景


// 生产者
channel.queueDeclare("task_queue", true, false, false, null); // 持久化队列

String message = "New task...";
channel.basicPublish("", "task_queue", 
    MessageProperties.PERSISTENT_TEXT_PLAIN, // 持久化消息
    message.getBytes());

// 消费者(Worker)
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
    String message = new String(delivery.getBody(), "UTF-8");
    System.out.println(" [x] Received '" + message + "'");
    // 模拟工作耗时
    try { Thread.sleep(1000); } catch (InterruptedException e) {}
    System.out.println(" [x] Done");
    channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
};
channel.basicConsume("task_queue", false, deliverCallback, consumerTag -> {});

发布/订阅模式

使用的交换机:Fanout 交换机(扇出交换机)

特点:
生产者发送的消息会被广播到所有绑定的队列

每个消费者都有自己的独立队列

// 生产者
channel.exchangeDeclare("logs", "fanout"); // 声明fanout交换机

String message = "Broadcast message!";
channel.basicPublish("logs", "", null, message.getBytes()); // 路由键为空

// 消费者(每个消费者有自己的临时队列)
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, "logs", ""); // 绑定到fanout交换机

路由模式

使用的交换机:Direct 交换机

特点:
生产者指定 routing_key,交换机根据 routing_key 将消息路由到匹配的队列

适用于精确匹配的消息分发(如 error、info 日志分类)

// 生产者
channel.exchangeDeclare("direct_logs", "direct"); // 声明direct交换机

String severity = "error"; // 路由键
String message = "Error log!";
channel.basicPublish("direct_logs", severity, null, message.getBytes());

// 消费者(只接收error级别的日志)
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, "direct_logs", "error"); // 绑定指定路由键

主题模式

使用的交换机:Topic 交换机

特点:
支持通配符匹配 *(单个单词)和 #(多个单词)

适用于更灵活的路由规则(如 logs.error.*、orders.#)

// 生产者
channel.exchangeDeclare("topic_logs", "topic"); // 声明topic交换机

String routingKey = "logs.error";
String message = "Topic message!";
channel.basicPublish("topic_logs", routingKey, null, message.getBytes());

// 消费者(使用通配符绑定)
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, "topic_logs", "logs.*"); // 匹配logs.开头的路由键

RPC模式

使用的交换机:默认交换机(Direct)或自定义交换机

特点
客户端发送请求消息
服务端处理请求并返回响应
使用回调队列和关联ID

// 客户端(发送RPC请求)
String callbackQueue = channel.queueDeclare().getQueue(); // 回调队列
AMQP.BasicProperties props = new AMQP.BasicProperties
    .Builder()
    .correlationId(UUID.randomUUID().toString())
    .replyTo(callbackQueue)
    .build();

channel.basicPublish("", "rpc_queue", props, "RPC request".getBytes());

// 服务端(处理RPC请求)
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
    AMQP.BasicProperties replyProps = new AMQP.BasicProperties
        .Builder()
        .correlationId(delivery.getProperties().getCorrelationId())
        .build();
    
    String response = processRpcRequest(new String(delivery.getBody(), "UTF-8"));
    channel.basicPublish("", delivery.getProperties().getReplyTo(), replyProps, response.getBytes());
    channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
};
channel.basicConsume("rpc_queue", false, deliverCallback, consumerTag -> {});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值