【RabbitMQ】工作队列模式(使用案例)

文章目录


咱们在前面学习了简单模式的写法,接下来学习另外几种工作模式的写法。

快速入门程序就是简单模式。此处省略。

1. Work Queues(工作队列)

它其实是简单模式的增强版,和简单模式的区别就是:简单模式有一个消费者,工作队列模式支持多个消费者接收消息,消费者之间是竞争关系,每个消息只能被一个消费者接收。

![步骤:

2、引入依赖

先引入 rabbitmq 的依赖

xml 复制代码
<!-- Source: https://mvnrepository.com/artifact/com.rabbitmq/amqp-client -->
<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>amqp-client</artifactId>
    <version>5.20.0</version>
    <scope>compile</scope>
</dependency>

3、生产者代码编写

工作队列模式和简单模式区别是有多个消费者,所以生产者消费者代码差异不大。

首先,咱们把配置文件单独领出来,定义为常量。

java 复制代码
public class Constants {
    public static final String HOST = "8.156.77.78";
    public static final int PORT = 5672;
    public static final String USERNAME = "edison";
    public static final String PASSWORD = "edison";
    public static final String VIRTUAL_HOST = "my_app_vhost";

    // 工作队列模式
    public static final String WORK_QUEUE = "work.queue";
}

相比简单模式,生产者的代码基本一样,为了能看到多个消费者竞争的关系,我们一次发送10条消息。

我们把发送消息的地方,改为一次发送 10 条消息即可。

java 复制代码
package work;

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

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Producer {
    public static void main(String[] args) throws IOException, TimeoutException {
        // 1. 建立连接
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(Constants.HOST);   // MQ所在的服务器地址
        factory.setPort(Constants.PORT);            // 端口号
        factory.setUsername(Constants.USERNAME);    // 账号
        factory.setPassword(Constants.PASSWORD);    // 密码
        factory.setVirtualHost(Constants.VIRTUAL_HOST);      // 虚拟主机
        Connection connection = factory.newConnection();

        // 2. 开启 channel 通道
        Channel channel = connection.createChannel();

        // 3. 声明交换机(使用内置的交换机即可)
        // ....

        // 4. 声明队列(如果队列不存在,则创建; 反之,存在就创建)
        channel.queueDeclare(Constants.WORK_QUEUE, true, false, false, null);

        // 5. 发送消息
        for (int i = 0; i < 10; i++) {
            String msg = "Hello work queue... " + i;
            channel.basicPublish("", Constants.WORK_QUEUE, null, msg.getBytes());
        }
        System.out.println("消息发生成功~~~");

        // 8. 资源释放
        channel.close();
        connection.close();
    }
}

4、消费者代码编写

消费者代码和简单模式一样,只是复制两份,两个消费者代码片段是一样的。

java 复制代码
package work;

import com.rabbitmq.client.*;
import constant.Constants;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class Consumer1 {
    public static void main(String[] args) throws IOException, TimeoutException {
        // 1. 建立连接
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost(Constants.HOST);   // MQ所在的服务器地址
        factory.setPort(Constants.PORT);            // 端口号
        factory.setUsername(Constants.USERNAME);    // 账号
        factory.setPassword(Constants.PASSWORD);    // 密码
        factory.setVirtualHost(Constants.VIRTUAL_HOST);      // 虚拟主机
        Connection connection = factory.newConnection();

        // 2. 开启 channel 通道
        Channel channel = connection.createChannel();

        // 3. 声明交换机(使用内置的交换机即可)
        // ....

        // 4. 声明队列(如果队列不存在,则创建; 反之,存在就创建)
        channel.queueDeclare(Constants.WORK_QUEUE, true, false, false, null);

        // 5. 消费消息
        DefaultConsumer consumer = new DefaultConsumer(channel) {
            // 从队列中收到消息后, 就会执行的方法
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
                // 收到消息以后就进行打印
                System.out.println("接收到消息: " + new String(body));
            }
        };
        channel.basicConsume(Constants.WORK_QUEUE, true, consumer);

        // 8. 资源释放
        //channel.close();
        //connection.close();
    }
}

5、观察结果

先启动两个消费者运行,再启动生产者。

为什么呢?如果先启动生产者,再启动消费者,由于消息较少,处理较快,那么第一个启动的消费者就会瞬间把 10 条消息消费掉,所以我们先启动两个消费者,再启动生产者。

先注释掉 Consumer 里面的【释放资源】的代码,然后分别启动 Consumer1 和 Consumer2,此时咱们的工作队列 work_queue 中就有两个消费者在等待

并且 Connections 的状态也是两个

然后启动 Producer 生产者的代码,让生产者发送 10 条消息到队列中去

此时 Consumer 1 收到的消息如下:

此时 Consumer 2 收到的消息如下:

并且在 RabbitMQ 的服务端上可以看到,此时队列里面是没有任何消息的,因为它被消费者瞬间就拿走了

相关推荐
就叫_这个吧17 小时前
RabbitMQ+elasticsearch+Redis,实现新增内容并异步到es中,是否消费成功检测
redis·elasticsearch·rabbitmq
肠畔码农18 小时前
深入分布式事务内核:从 2PC/XA 到 Seata AT 模式的架构演进与权衡
分布式·架构
ai小陈19 小时前
PyTorch多GPU分布式训练实战:从单卡脚本迁移到DDP
服务器·人工智能·pytorch·分布式·深度学习·ai·gpu算力
伟大的大威20 小时前
三台 DGX Spark 部署 DeepSeek V4 Flash NVFP4:从零到可用教程
大数据·分布式·spark
阿里云云原生20 小时前
企业级实时数据平台建设:利用存算分离 Kafka 实现低成本、高可靠入湖
分布式·阿里云·云原生·kafka
国科安芯21 小时前
星载CANFD总线通信网络中抗辐射微控制器MCU的失效机理与容错设计研究
网络·人工智能·分布式·单片机·嵌入式硬件·架构·抗辐射加固
zcmodeltech21 小时前
污水处理设备沙盘模型控制系统设计与实现:多单元协同联动方案
网络·分布式·stm32·单片机·嵌入式硬件·交互
roman_日积跬步-终至千里1 天前
Spark 资源配置与 Shuffle 故障排查生产手册
大数据·分布式·spark
roman_日积跬步-终至千里1 天前
常驻 Spark 引擎的稳定性风险:从一次 Linkis 任务失败说起
大数据·分布式·spark
JAVA面经实录9171 天前
Kafka面试题标准答案(面试背诵版)
分布式·面试·kafka