消息队列——rabbitmq的不同工作模式

2023-07-17 01:40:04

目录

Work queues 工作队列模式

 Pub/Sub 订阅模式

Routing路由模式

Topics通配符模式 

 工作模式总结


Work queues 工作队列模式

C1和C2属于竞争关系,一个消息只有一个消费者可以取到。

 代码部分只需要用两个消费者进程监听同一个队里即可。

两个消费者呈现竞争关系。

用一个生产者推送10条消息

        for(int i=0;i<10;i++)
        {
            String body=i+"hello rabbitmq!!!";
            channel.basicPublish("","work_queues",null,body.getBytes());
        }

两个监听的消费者接收情况如下。 

 

 Pub/Sub 订阅模式

一个生产者发送消息后有两个消费者可以收到消息。

生产者把消息发给交换机,交换机再把消息通过Routes路由分发给不同的队列。

//发送消息
public class producer_PubSub {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost(""); //设置ip地址。默认为127.0.0.1
        factory.setPort(5672);              //端口 默认值5672
        factory.setVirtualHost("/itcast");  //设置虚拟机 默认值/
        factory.setUsername("yhy");        //用户名,默认值guest
        factory.setPassword("");     //密码,默认值guest
        //3.创建连接Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();

        /*
        * exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments)
        * 参数:
        * 1.exchange  : 交换价名称
        * 2.type      : 交换机类型 ,有四种
        *               DIRECT("direct"),  定向
                        FANOUT("fanout"),   扇形(广播),发送消息到每一个与之绑定队列
                        TOPIC("topic"),     通配符的方式
                        HEADERS("headers"); 参数匹配
        *3.durable  :是否持久化
        * 4.autoDelete:是否自动删除
        * 5.internal: 内部使用。一般false
        * 6.arguments:参数
        * */
        //5.创建交换机
        String exchangeName="test_fanout";
        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.FANOUT,true,false,false,null);
        //6.创建队列
        String queue1Name="test_fanout_queue1";
        String queue2Name="test_fanout_queue2";
        channel.queueDeclare(queue1Name,true,false,false,null);
        channel.queueDeclare(queue2Name,true,false,false,null);

        /*
        * queueBind(String queue, String exchange, String routingKey)
        * 参数:
        * queue:队列名
        * exchange:交换机名称
        * routingKey:路由键,绑定规则
        *   如果交换机类型为fanout,routingKey设置为""
        * */
        //7.绑定队列和交换机
        channel.queueBind(queue1Name,exchangeName,"");
        channel.queueBind(queue2Name,exchangeName,"");

        String body="日志信息:调用了findAll方法";
        //8.发送消息
        channel.basicPublish(exchangeName,"",null,body.getBytes());
        //9.释放资源
        channel.close();
        connection.close();
    }
}

 运行之后两个队列里面就会多一条消息

两个消费者的代码大同小异,只是绑定的队列名不同,这里只给其中一个

public class consumer_PubSub1 {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost(""); //设置ip地址。默认为127.0.0.1
        factory.setPort(5672);              //端口 默认值5672
        factory.setVirtualHost("/itcast");  //设置虚拟机 默认值/
        factory.setUsername("yhy");        //用户名,默认值guest
        factory.setPassword("");     //密码,默认值guest
        //3.创建连接Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();

        String queue1Name="test_fanout_queue1";
        String queue2Name="test_fanout_queue2";
        /*
        * basicConsume(String queue, boolean autoAck, Consumer callback)
        * 参数:
        *   1.队列名称
        *   2.autoAck:是否自动确认
        *   3.callback:回调对象
        * */
        //6.接收消息
        Consumer consumer=new DefaultConsumer(channel){
            /*
            * 回调方法,当收到消息后,会自动执行该方法
            * 1.consumerTag:标识
            * 2.envelope :获取一些信息,交换机,路由key...
            * 3.properties: 配置信息
            * 4.body: 数据
            * */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//                System.out.println("consumerTag:"+consumerTag);
//                System.out.println("Exchange:"+envelope.getExchange());
//                System.out.println("RoutingKey:"+envelope.getRoutingKey());
//                System.out.println("properties:"+properties);
                System.out.println("body:"+new String(body));
                System.out.println("将日志信息打印到控制台......");
            }
        };
        channel.basicConsume(queue1Name,true,consumer);

        //不需要关闭资源
    }
}

 控制台输出有

Routing路由模式

对于特定级别的信息会发送到别的队列,如上图的error,在发送消息时也会有一个routing,只要和后面的队列对应上就可以发送到对应队列。 

 生产者代码:

//发送消息
public class producer_Routing {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost(""); //设置ip地址。默认为127.0.0.1
        factory.setPort(5672);              //端口 默认值5672
        factory.setVirtualHost("/itcast");  //设置虚拟机 默认值/
        factory.setUsername("yhy");        //用户名,默认值guest
        factory.setPassword("");     //密码,默认值guest
        //3.创建连接Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();

        /*
        * exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments)
        * 参数:
        * 1.exchange  : 交换价名称
        * 2.type      : 交换机类型 ,有四种
        *               DIRECT("direct"),  定向
                        FANOUT("fanout"),   扇形(广播),发送消息到每一个与之绑定队列
                        TOPIC("topic"),     通配符的方式
                        HEADERS("headers"); 参数匹配
        *3.durable  :是否持久化
        * 4.autoDelete:是否自动删除
        * 5.internal: 内部使用。一般false
        * 6.arguments:参数
        * */
        //5.创建交换机
        String exchangeName="test_direct";
        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.DIRECT,true,false,false,null);
        //6.创建队列
        String queue1Name="test_direct_queue1";
        String queue2Name="test_direct_queue2";
        channel.queueDeclare(queue1Name,true,false,false,null);
        channel.queueDeclare(queue2Name,true,false,false,null);

        /*
        * queueBind(String queue, String exchange, String routingKey)
        * 参数:
        * queue:队列名
        * exchange:交换机名称
        * routingKey:路由键,绑定规则
        *   如果交换机类型为fanout,routingKey设置为""
        * */
        //7.绑定队列和交换机
        //队列1绑定error

        channel.queueBind(queue1Name,exchangeName,"error");

        //队列2绑定error,info,warning
        channel.queueBind(queue2Name,exchangeName,"info");
        channel.queueBind(queue2Name,exchangeName,"error");
        channel.queueBind(queue2Name,exchangeName,"warning");

        String body="日志信息:调用了findAll方法,级别:info,error,warning";
        //8.发送消息
        channel.basicPublish(exchangeName,"error",null,body.getBytes());
        //9.释放资源
        channel.close();
        connection.close();
    }
}

消费者代码(两个消费者就绑定队列名不一样):

public class consumer_Routing1 {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost(""); //设置ip地址。默认为127.0.0.1
        factory.setPort(5672);              //端口 默认值5672
        factory.setVirtualHost("/itcast");  //设置虚拟机 默认值/
        factory.setUsername("yhy");        //用户名,默认值guest
        factory.setPassword("");     //密码,默认值guest
        //3.创建连接Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();

        String queue1Name="test_direct_queue1";
        String queue2Name="test_direct_queue2";
        /*
        * basicConsume(String queue, boolean autoAck, Consumer callback)
        * 参数:
        *   1.队列名称
        *   2.autoAck:是否自动确认
        *   3.callback:回调对象
        * */
        //6.接收消息
        Consumer consumer=new DefaultConsumer(channel){
            /*
            * 回调方法,当收到消息后,会自动执行该方法
            * 1.consumerTag:标识
            * 2.envelope :获取一些信息,交换机,路由key...
            * 3.properties: 配置信息
            * 4.body: 数据
            * */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//                System.out.println("consumerTag:"+consumerTag);
//                System.out.println("Exchange:"+envelope.getExchange());
//                System.out.println("RoutingKey:"+envelope.getRoutingKey());
//                System.out.println("properties:"+properties);
                System.out.println("body:"+new String(body));
                System.out.println("将日志信息存储到数据库");
            }
        };
        channel.basicConsume(queue1Name,true,consumer);

        //不需要关闭资源
    }
}

Topics通配符模式 

发送消息时设定的routingkey会和后面的routingkey进行匹配。

生产者代码:

//发送消息
public class producer_Topic {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost(""); //设置ip地址。默认为127.0.0.1
        factory.setPort(5672);              //端口 默认值5672
        factory.setVirtualHost("/itcast");  //设置虚拟机 默认值/
        factory.setUsername("yhy");        //用户名,默认值guest
        factory.setPassword("");     //密码,默认值guest
        //3.创建连接Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();

        /*
        * exchangeDeclare(String exchange, BuiltinExchangeType type, boolean durable, boolean autoDelete, boolean internal, Map<String, Object> arguments)
        * 参数:
        * 1.exchange  : 交换价名称
        * 2.type      : 交换机类型 ,有四种
        *               DIRECT("direct"),  定向
                        FANOUT("fanout"),   扇形(广播),发送消息到每一个与之绑定队列
                        TOPIC("topic"),     通配符的方式
                        HEADERS("headers"); 参数匹配
        *3.durable  :是否持久化
        * 4.autoDelete:是否自动删除
        * 5.internal: 内部使用。一般false
        * 6.arguments:参数
        * */
        //5.创建交换机
        String exchangeName="test_topic";
        channel.exchangeDeclare(exchangeName, BuiltinExchangeType.TOPIC,true,false,false,null);
        //6.创建队列
        String queue1Name="test_topic_queue1";
        String queue2Name="test_topic_queue2";
        channel.queueDeclare(queue1Name,true,false,false,null);
        channel.queueDeclare(queue2Name,true,false,false,null);

        /*
        * queueBind(String queue, String exchange, String routingKey)
        * 参数:
        * queue:队列名
        * exchange:交换机名称
        * routingKey:路由键,绑定规则
        *   如果交换机类型为fanout,routingKey设置为""
        * */
        //7.绑定队列和交换机
        // routing key 系统的名称.日志的级别。
        //需求:所有error级别的日志存入数据库,所有order系统的日志存入数据库
        channel.queueBind(queue1Name,exchangeName,"#.error");
        channel.queueBind(queue1Name,exchangeName,"order.*");
        channel.queueBind(queue2Name,exchangeName,"*.*");

        String body="日志信息:调用了findAll方法";
        //8.发送消息
        channel.basicPublish(exchangeName,"goods.error",null,body.getBytes());
        //9.释放资源
        channel.close();
        connection.close();
    }
}

 消费者代码

public class consumer_Topic1 {
    public static void main(String[] args) throws IOException, TimeoutException {
        //1.创建连接工厂
        ConnectionFactory factory=new ConnectionFactory();
        //2.设置参数
        factory.setHost(""); //设置ip地址。默认为127.0.0.1
        factory.setPort(5672);              //端口 默认值5672
        factory.setVirtualHost("/itcast");  //设置虚拟机 默认值/
        factory.setUsername("yhy");        //用户名,默认值guest
        factory.setPassword("");     //密码,默认值guest
        //3.创建连接Connection
        Connection connection = factory.newConnection();
        //4.创建Channel
        Channel channel = connection.createChannel();

        String queue1Name="test_topic_queue1";
        String queue2Name="test_topic_queue2";
        /*
        * basicConsume(String queue, boolean autoAck, Consumer callback)
        * 参数:
        *   1.队列名称
        *   2.autoAck:是否自动确认
        *   3.callback:回调对象
        * */
        //6.接收消息
        Consumer consumer=new DefaultConsumer(channel){
            /*
            * 回调方法,当收到消息后,会自动执行该方法
            * 1.consumerTag:标识
            * 2.envelope :获取一些信息,交换机,路由key...
            * 3.properties: 配置信息
            * 4.body: 数据
            * */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
//                System.out.println("consumerTag:"+consumerTag);
//                System.out.println("Exchange:"+envelope.getExchange());
//                System.out.println("RoutingKey:"+envelope.getRoutingKey());
//                System.out.println("properties:"+properties);
                System.out.println("body:"+new String(body));
                System.out.println("将日志信息存储到数据库");
            }
        };
        channel.basicConsume(queue1Name,true,consumer);

        //不需要关闭资源
    }
}

 工作模式总结

更多推荐

进程转态及其转换过程

一.进程转态及其转换过程在Linux操作系统中,进程的状态可以相互转换,下面是不同状态之间的相互转换:就绪态(ReadyState):当一个进程创建后,它被放入就绪态。此时,进程已经被加载到内存中,并准备好被CPU分配时间片来执行。运行态(RunningState):当就绪态的进程获得CPU时间片后,进程的状态会从就绪

国产手机芯片4G方案_紫光展锐安卓核心板虎贲4G智能模块方案定制

元器件清单即BOM物料清单,不同行业领域的BOM表侧重点不一样。安卓主板的BOM表则侧重点在于元器件物料的清单,也就是安卓电路板的PCBA清单,精密的安卓板有上千个物料,可以帮助我们估算物料成本,建立生产计划,控制库存等。紫光展锐核心板,基于Android操作系统,支持全国产项目快递部署及开发。新移科技研发的紫光展锐平

基于Java+微信小程序实现《电子点餐系统》

博主介绍:✌全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌🍅文末获取源码联系🍅👇🏻精彩专栏推荐订阅👇🏻不然下次找不到哟2022-2024年最全的计算机软件毕业设计选题

网络安全(黑客)自学

前言作为一个合格的网络安全工程师,应该做到攻守兼备,毕竟知己知彼,才能百战百胜。娱乐圈:主要是初中生和高中生较多,玩网恋,人气,空间,建站收徒玩赚钱,技术高的也是有的,只是很少见。技术圈:这个圈子里面的黑客是为了能把黑客技术玩到极致的技术狂人,我最佩服的就是这群人,希望以后自己也能成为这样的人。职业圈:这里面的人群主要

springboot

Springboot入门Springboot入门springboot提供了一种快速使用spring项目的方式,而不是对spring功能的增强,本文参考https://www.bilibili.com/video/BV1Lq4y1J77x?p=12&vd_source=0882f549dac54045384d4a9215

vue的事件处理

1、监听事件我们可以使用v-on指令(通常缩写为@符号)来监听DOM事件,并在触发事件时执行一些JavaScript。用法为v-on:click=“methodName”或使用快捷方式@click=“methodName”例如:<divid="basic-event"><button@click="counter+=1

✽js的快速入门5 window对象

BOM浏览器对象模型:是规范浏览器对js语言的支持(js调用浏览器本身功能)BOM的具体实现是window对象window对象使用1.不用new直接进行使用即可,类似Math的使用方式,window关键字可以省略不写window.document等等2.框体方法<!DOCTYPEhtml><htmllang="en">

vue中的 render 和 h() 详解

vue中的render和h()详解当使用Vue.js进行前端开发时,理解和掌握"render"函数和"h()"函数是非常重要的,因为它们是Vue组件的核心构建和渲染部分render和h()是在Vue.js中常用的两个概念,它们通常用于创建和渲染Vue组件。什么是"render"函数?"render"函数是Vue组件的一

Vue系列之入门篇

前言:目录一,关于Vue的简介1.什么是Vue?2.使用Vue框架的好处?3.库和框架的区别:4.MVVM的介绍5.Vue的入门案例二,Vue的生命周期一,关于Vue的简介1.什么是Vue?Vue是一个构建用户界面(UI)的渐进式JavaScript框架2.使用Vue框架的好处?简单易学:Vue的API设计简洁,易于理

(一)探索随机变量及其分布:概率世界的魔法

文章目录🍋引言🍋什么是随机变量?🍋离散随机变量🍋连续随机变量🍋随机变量的概率分布🍋离散概率分布🍋0-1分布(Bernoulli分布)🍋二项分布(Binomial分布)🍋泊松分布(Poisson分布)🍋几何分布(Geometric分布)🍋连续概率分布🍋均匀分布(UniformDistributio

基于Java+微信小程序实现《微信阅读平台》

博主介绍:✌全网粉丝30W+,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌🍅文末获取源码联系🍅👇🏻精彩专栏推荐订阅👇🏻不然下次找不到哟2022-2024年最全的计算机软件毕业设计选题

热文推荐