RabbitMQ的工作队列有哪些?带你玩转工作队列_mq指定工作队列

  • 参数讲解:
参数含义
exchange要将消息发送到交换机的名称
routingKey路由key
props一些配置信息
body消息内容

3、basicConsume

  • 源码:
String basicConsume(String queue, boolean autoAck, DeliverCallback deliverCallback, CancelCallback cancelCallback) throws IOException;

  • 参数讲解:
参数含义
queue消费队列的名称
autoAck消费成功之后是否要自动应答
deliverCallback当一个消息发送过来后的回调接口
cancelCallback当一个消费者取消订阅时的回调接口

注意:

自动确认 autoAck = true 只要消息从队列中获取,无论消费者获取到消息后是否成功消费消息,都认为是消息已经成功消费。
手动确认 autoAck = false 消费者从队列中获取消息后,服务器会将该消息标记为不可用状态,等待消费者的反馈,如果消费者一直没有反馈,那么该消息将一直处于不可用状态。


三、简单模式

在这里插入图片描述

  • 生产者代码:我们向消费者发送了消息你好,MessageQueue
public class Producer {
    public static void main(String[] args) throws Exception {
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = RabbitMqUtils.getChannel();
        channel.queueDeclare("hello", false, false, false, null);
        channel.basicPublish("", "hello", null, "你好,MessageQueue".getBytes());
        // 释放资源
        channel.close();
        connection.close();
    }
}

当我们执行生产者代码,就会产生一个带有数据的队列:

在这里插入图片描述

  • 消费者代码:
public class Consumer {
    public static void main(String[] args) throws Exception {
        Connection connection = RabbitMqUtils.getConnection();
        Channel channel = RabbitMqUtils.getChannel();
        // 声明 接收消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println(new String(message.getBody()));
        };
        // 取消消息时的回调
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("消息消费被中断");
        };
        channel.basicConsume("hello", true, deliverCallback, cancelCallback);
    }
}

当我们执行完消费者代码,可以看到控制台界面和消息被消费

在这里插入图片描述

在这里插入图片描述


四、Work模式

在这里插入图片描述

一个生产者对应多个消费者,但是一条消息只能由一个消费者消费。
主要有两种模式:一是轮询模式的分发,一个消费者一条消息,按均分配;二是公平分发,根据消费者的消费能力进行公平分发,能力越高,消费能力越强,按劳分配。

  • 接下来主要介绍轮询模式,生产者代码:
public class Producer {
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        channel.queueDeclare("work", false, false, false, null);
        for (int i = 1; i <= 10; i++) {
            Thread.sleep(i \* 10);
            channel.basicPublish("", "work", null, (i + "I'am rabbitMQ").getBytes());
        }
        RabbitMqUtils.closeChannel();
        RabbitMqUtils.closeConnection();
    }
}

  • 消费者1的代码:
public class Work\_1 {
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            try {
                Thread.sleep(1000);
                System.out.println(new String(message.getBody()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            channel.basicAck(message.getEnvelope().getDeliveryTag(), false);
        };
        CancelCallback cancelCallback = (consumerTag) -> {
            System.out.println("消息消费被中断");
        };
// channel.basicQos(1);
        channel.basicConsume("work", false, deliverCallback, cancelCallback);
        RabbitMqUtils.closeChannel();
        RabbitMqUtils.closeConnection();
    }
}

  • 消费者2的代码:
public class Work\_2 {
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        // 声明 接收消息
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            try {
                Thread.sleep(5 \* 1000);
                System.out.println(new String(message.getBody()));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //返回确定状态,由于我们是设置手动返回状态的,如果没有调用该方法,那么消息仍然在我们队列中,不会被删除
            channel.basicAck(message.getEnvelope().getDeliveryTag(), false);
        };
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("消息消费被中断");
        };
// channel.basicQos(1);
        channel.basicConsume("work", false, deliverCallback, cancelCallback);
        RabbitMqUtils.closeChannel();
        RabbitMqUtils.closeConnection();
    }
}

  • 接着开始测试代码,首先让生产者发送10条消息到队列中,然后运行消费者代码,打开控制台,如图:

在这里插入图片描述

在这里插入图片描述

我们可以发现,即使两个消费者的睡眠时间不同(处理消息的能力不一样),但是消费消息的数目确实一样的。

分析运行结果:

1、消费者1和消费者2获取到的消息内容是不同的,即同一个消息只能被一个消费者获取。
2、两个消费者获取消息的条数是一样的。

  • 而对于公平分发,我们只需要在上述代码中添加下列代码:
channel.basicQos(1);


五、发布/订阅模式

在这里插入图片描述

P:在订阅模式中,多了一个Exchange角色,生产者不再发送到队列中,而是发送给交换机。
Exchange:一方面接收生产者发送的消息,另一方面知道如何处理消息;而到底如何处理,取决于Exchange的类型。有常见的以下三种类型:

  • Fanout:广播,将消息交给所有绑定到交换机的队列
  • Direct:定向,把消息交给符合指定routing key的队列
  • Topic:通配符,把消息交给符合routing pattern的队列

注意:交换机只负责转发消息,不具备存储信息的能力,因此如果没有任何队列与交换机绑定,或者没有符合路由规则的队列,那么信息会丢失!

  • 生产者代码:
public class Producer {
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        /\*
 String exchange:交换机名称
 BuiltinExchangeType type:交换机类型
 boolean durable:是否持久化
 boolean autoDelete:自否自动删除
 boolean internal:内部使用,一般为false
 Map<String, Object> arguments:参数
 \*/
        channel.exchangeDeclare("\_fanout", BuiltinExchangeType.FANOUT, false, false, false, null);
        channel.queueDeclare("\_fanout\_1", false, false, false, null);
        channel.queueDeclare("\_fanout\_2", false, false, false, null);
        // 绑定队列和交换机
        /\*
 String queue:队列名称
 String exchange:交换机名称
 String routingKey:路由键
 规则:如果交换机的类型为fanout,routingkey设置为""
 \*/
        channel.queueBind("\_fanout\_1", "\_fanout", "");
        channel.queueBind("\_fanout\_2", "\_fanout", "");
        channel.basicPublish("\_fanout", "", null, "日志信息:张三调用了XXX方法,日志级别为info".getBytes());
        channel.close();
        RabbitMqUtils.closeConnection();
    }
}

  • 消费者1代码:
public class PubSun\_1 {
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println(new String(message.getBody()));
            System.out.println("获取信息,并打印到控制台");
        };
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("消息消费被中断");
        };
        channel.basicConsume("\_fanout\_1", true, deliverCallback, cancelCallback);
    }
}

  • 消费者2代码:
public class PubSun\_2 {
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println(new String(message.getBody()));
            System.out.println("获取信息,并保存到数据库");
        };
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("消息消费被中断");
        };
        channel.basicConsume("\_fanout\_2", true, deliverCallback, cancelCallback);
    }
}

  • 运行生产者代码,可以看到控制台的打印信息如下:

在这里插入图片描述

在这里插入图片描述


六、路由模式

在这里插入图片描述

在此模式下,队列与交换机不能任意绑定,而是要指定一个RoutingKey(路由key);生产者在向交换机发送消息时,也必须指定消息的RoutingKey。

交换机不再把消息交给每一个绑定的队列,而是根据消息的路由key进行判断,只有队列的路由key与消息的路由key完全一致,才会接收到消息。

  • 生产者代码:
public class Producer {
    // 发消息
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        channel.exchangeDeclare("routing", BuiltinExchangeType.DIRECT, false, false, false, null);
        channel.queueDeclare("\_routing\_1", false, false, false, null);
        channel.queueDeclare("\_routing\_2", false, false, false, null);
        // 绑定队列和交换机
        channel.queueBind("\_routing\_1", "routing", "error");
        channel.queueBind("\_routing\_2", "routing", "error");
        channel.queueBind("\_routing\_2", "routing", "info");
        channel.queueBind("\_routing\_2", "routing", "warning");
        channel.basicPublish("routing", "info", null, "日志信息:张三调用了XXX方法,日志级别为info".getBytes());
        channel.close();
        RabbitMqUtils.closeConnection();
    }
}

  • 消费者1代码:
public class Routing1 {
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            System.out.println(new String(message.getBody()));
            System.out.println("获取信息,并保存到数据库");
        };
        CancelCallback cancelCallback = consumerTag -> {
            System.out.println("消息消费被中断");
        };
        channel.basicConsume("\_routing\_1", true, deliverCallback, cancelCallback);
    }
}

  • 消费者2代码:
public class Routing2 {
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        DeliverCallback deliverCallback = (consumerTag, message) -> {


![img](https://img-blog.csdnimg.cn/img_convert/170e9d30f953d7619b97bd0da6819f11.png)
![img](https://img-blog.csdnimg.cn/img_convert/c15f10ad3403c3b8c7b6d934751b63c6.png)
![img](https://img-blog.csdnimg.cn/img_convert/1455894ae62ca8e9e5a3627d39bcb2e3.png)

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

 channel = RabbitMqUtils.getChannel();
        DeliverCallback deliverCallback = (consumerTag, message) -> {


[外链图片转存中...(img-LdqK5ffh-1714161527732)]
[外链图片转存中...(img-BNC7gsQP-1714161527733)]
[外链图片转存中...(img-M1JTShxH-1714161527733)]

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!**

**由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新**

**[需要这份系统化资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618545628)**

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值