RabbitMQ工作模式——Routing模式(路由模式、附代码)

大伙可以到我的RabbitMQ专栏获取更多信息

demo示例这里拿

模式说明

以日志存储使用场景为例,日志分为不同级别:error、info、warning、debug、trace等,不同日志级别的日志量也是不一样的,级别越高日志量相对越小。

通常情况下因为不同级别日志的数量级不一样,其对应的处理方式也不一样:

有些情况下日志需要入库,数据库不能承受大量日志存储,一般来说数量级较小的日志界别可以直接入库,例如error级别的日志;info级别的日志由于数量级较大可能会先暂存于缓存中,之后再对其做细致的处理。

在此场景下就要使用MQ中的交换机对不同的log message做不同的转发,将error级别的日志传递给入库系统对应的队列,将info级别的日志传递给缓存系统对应的队列,简单的理解就是交换机会将不同的message根据路由规则“分门别类”,这就是Routing模式的典型使用场景。

Routing Key

交换机是怎么进行message的“分门别类”呢?

就需要用到Routing Key,Routing key是队列和交换机绑定的时候的一个标识,生产者在向MQ push message的时候需要带上Routing key,这样交换机可以根据不同message的Routing key来与队列进行匹配,当匹配成功的时候,交换机就将该message传递给该队列,进而达到了message按照规则分发的效果。

生产者

与订阅模式基本相似,只不过订阅模式没有设置routing key,并且设置交换机模式为 DIRECT 类型

在绑定队列到路由器的时候指定该队列的routing key,发布消息的时候也给该消息执行routing key,当消息进入路由器之后开始匹配routing key,当成功匹配到队列后,将该消息传递给该队列。

package com.leolee.rabbitmq;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

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

/**
 * @ClassName ProducerPubSub
 * @Description: Rounting模式
 * @Author LeoLee
 * @Date 2020/11/6
 * @Version V1.0
 **/
public class ProducerRouting {

    public static void main(String[] args) throws IOException, TimeoutException {

        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //2.设置参数
        connectionFactory.setHost("127.0.0.1");//默认值为localhost
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/LeoLee");//默认值为:/
        connectionFactory.setUsername("LeoLee");
        connectionFactory.setPassword("lyl512240816");

        //3.创建连接 connection
        Connection connection = connectionFactory.newConnection();

        //4.创建channel
        Channel channel = connection.createChannel();

        //5.创建交换机
        /*
        String exchange:交换机名称
        BuiltinExchangeType type:交换机类型,枚举,
        boolean durable:是否持久化
        boolean autoDelete:是否自动删除,当没有消费者的时候自动删除
        boolean internal:是否内部使用,一般都是false,true代表给MQ内部使用的,比如给MQ开发的插件使用
        Map<String, Object> arguments:相关参数
         */
        String exchangerName = "test_direct";
        channel.exchangeDeclare(exchangerName, BuiltinExchangeType.DIRECT, false, false, false, null);

        //6.创建队列
        /*
         String queue:队列名称
         boolean durable:是否持久化
         boolean exclusive: 有如下两个意义
            是否独占,只有一个消费者监听这个队列
            当connection关闭时,是否删除队列
         boolean autoDelete:是否自动删除,当没有消费者的时候自动删除
         Map<String, Object> arguments: 一些配置参数
         */
        //如果没有一个名字叫xxx的队列,则会创建,如果存在该队列,则复用
        String queueName1 = "test_direct_queue1";
        String queueName2 = "test_direct_queue2";
        channel.queueDeclare(queueName1, false, false, false, null);
        channel.queueDeclare(queueName2, false, false, false, null);

        //7.绑定队列和交换机
        /*
        String queue:队列名称
        String exchange:交换机名称
        String routingkey:路由键,绑定规则
            如果交换机的类型为 fanout,routingkey设置为空值""
        */
        channel.queueBind(queueName1, exchangerName, "errorLog");

        channel.queueBind(queueName2, exchangerName, "infoLog");
        channel.queueBind(queueName2, exchangerName, "warningLog");

        //8.发送消息
        String body1 = "日志信息[error]:又是不想当社畜的一天";
        String body2 = "日志信息[info]:又是不想当社畜的一天";
        String body3 = "日志信息[warning]:又是不想当社畜的一天";
        channel.basicPublish(exchangerName, "infoLog", null, body2.getBytes());//第二个参数routingkey为空
        channel.basicPublish(exchangerName, "errorLog", null, body1.getBytes());//第二个参数routingkey为空
        channel.basicPublish(exchangerName, "warningLog", null, body3.getBytes());//第二个参数routingkey为空

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

    }

}

运行生产者:

消息已经成功发送到了对应的routing key的队列

消费者

绑定对应的队列即可

以下是其中一个消费者的代码,另一个一摸一样,改一下绑定队列

package com.leolee.rabbitmq;

import com.rabbitmq.client.*;

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

/**
 * @ClassName ConsumerPubSub1
 * @Description: Routing模式
 * @Author LeoLee
 * @Date 2020/11/6
 * @Version V1.0
 **/
public class ConsumerRouting1 {

    public static void main(String[] args) throws IOException, TimeoutException {

        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();

        //2.设置参数
        connectionFactory.setHost("127.0.0.1");//默认值为localhost
        connectionFactory.setPort(5672);
        connectionFactory.setVirtualHost("/LeoLee");//默认值为:/
        connectionFactory.setUsername("LeoLee");
        connectionFactory.setPassword("lyl512240816");

        //3.创建连接 connection
        Connection connection = connectionFactory.newConnection();

        //4.创建channel
        Channel channel = connection.createChannel();

        //5.创建队列queue(由于简单模式不需要Exchange,其实是使用默认的交换机,所以消息直接入队列),消费者可以不需要创建队列,但是创建了也不影响
        /*
         String queue:队列名称
         boolean durable:是否持久化
         boolean exclusive: 有如下两个意义
            是否独占,只有一个消费者监听这个队列
            当connection关闭时,是否删除队列
         boolean autoDelete:是否自动删除,当没有消费者的时候自动删除
         Map<String, Object> arguments: 一些配置参数
         */
        //如果没有一个名字叫Hello_world的队列,则会创建,如果存在该队列,则复用
        //生产者已经生命过了队列,可以忽略该步骤
        //channel.queueDeclare("workQueues", false, false, false, null);
        String queueName1 = "test_direct_queue1";

        //6.接收消息
        /*
         * String queue:队列名称
         * boolean autoAck:是否自动确认,当消费者收到消息之后会自动给MQ一个回执,告诉MQ消息已经收到
         * Consumer callback:回调方法
         */
        Consumer consumer = new DefaultConsumer(channel){

            /*
             * 功能描述: <br>
             * 〈回调方法〉当客户端收到消息并向MQ确认消息已经收到,将回调该方法
             * @Param: [consumerTag消息唯一标识,
             *  envelope获取一些信息,包含交换机信息、routing key...等,
             *  properties配置信息,生产者发送消息时候的配置,
             *  body数据]
             * @Return: void
             * @Author: LeoLee
             * @Date: 2020/11/5 11:56
             */
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {

                /*System.out.println("consumerTag:" + consumerTag);
                System.out.println("envelope.exchange:" + envelope.getExchange());
                System.out.println("envelope.routingKey:" + envelope.getRoutingKey());
                System.out.println("properties:" + properties);*/
                System.out.println("消费者1从队列" + queueName1 + "接收到body:" + new String(body));

            }
        };
        channel.basicConsume(queueName1, true, consumer);

        //7.消费者不需要关闭资源,不然无法完成自动确认
    }
}

运行两个绑定不同队列的消费者

可以看出,消息确实在交换机根据其绑定的routing key被分发到了指定的队列中

 

 

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
RabbitMQ提供了6种工作模式,包括简单模式、work queues、Publish/Subscribe发布与订阅模式Routing路由模式、Topics主题模式、RPC远程调用模式(不太符合MQ)。这些模式分别具有不同的特点和使用场景。简单模式是最基本的模式,消息发送到队列中被消费者接收。工作队列模式是多个消费者共同消费一个队列中的消息。Publish/Subscribe发布与订阅模式中,生产者将消息发送到交换机,然后交换机将消息广播给所有绑定的队列。Routing路由模式是生产者选择将消息发送到特定的路由键上,消费者通过绑定队列和路由键来接收消息。Topics主题模式类似于Routing模式,但是可以使用通配符进行匹配路由键。RPC远程调用模式用于远程调用服务,不太符合消息队列的特点。 可以看出,这些模式在消息的传输、消费者的数量、消息的路由等方面有所不同。工作队列模式不需要定义交换机,而发布/订阅模式需要定义交换机。发布/订阅模式是面向交换机发送消息,而工作队列模式是面向队列发送消息(底层使用默认交换机)。发布/订阅模式需要设置队列和交换机的绑定,而工作队列模式不需要设置,实际上工作队列模式会将队列绑定到默认的交换机。 综上所述,RabbitMQ工作模式包括简单模式、work queues、Publish/Subscribe发布与订阅模式Routing路由模式、Topics主题模式、RPC远程调用模式。每种模式在实际应用中有不同的用途和特点,可以根据具体需求选择合适的工作模式。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [RabbitMQ工作模式](https://blog.csdn.net/weixin_42440154/article/details/124689685)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [RabbitMQ六种工作模式详解](https://blog.csdn.net/qq_44760609/article/details/125084962)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值