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

目录

[Work queues 工作队列模式](#Work queues 工作队列模式)

[Pub/Sub 订阅模式](#Pub/Sub 订阅模式)

Routing路由模式

Topics通配符模式

工作模式总结


Work queues 工作队列模式

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

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

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

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

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

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

Pub/Sub 订阅模式

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

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

java 复制代码
//发送消息
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();
    }
}

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

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

java 复制代码
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,只要和后面的队列对应上就可以发送到对应队列。

生产者代码:

java 复制代码
//发送消息
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();
    }
}

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

java 复制代码
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进行匹配。

生产者代码:

java 复制代码
//发送消息
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();
    }
}

消费者代码

java 复制代码
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);

        //不需要关闭资源
    }
}

工作模式总结

相关推荐
RainbowSea14 小时前
6. RabbitMQ 死信队列的详细操作编写
java·消息队列·rabbitmq
RainbowSea15 小时前
5. RabbitMQ 消息队列中 Exchanges(交换机) 的详细说明
java·消息队列·rabbitmq
数据智能老司机16 小时前
CockroachDB权威指南——CockroachDB SQL
数据库·分布式·架构
数据智能老司机16 小时前
CockroachDB权威指南——开始使用
数据库·分布式·架构
数据智能老司机17 小时前
CockroachDB权威指南——CockroachDB 架构
数据库·分布式·架构
IT成长日记17 小时前
【Kafka基础】Kafka工作原理解析
分布式·kafka
州周19 小时前
kafka副本同步时HW和LEO
分布式·kafka
ChinaRainbowSea20 小时前
1. 初始 RabbitMQ 消息队列
java·中间件·rabbitmq·java-rabbitmq
爱的叹息20 小时前
主流数据库的存储引擎/存储机制的详细对比分析,涵盖关系型数据库、NoSQL数据库和分布式数据库
数据库·分布式·nosql
千层冷面21 小时前
RabbitMQ 发送者确认机制详解
分布式·rabbitmq·ruby