rabbitmq-----Routing和topic模式

前几篇已经说了mq的基本用法,也分别使用了普通的java写法和spring boot基于注解的方法去实现了mq的接收消息。我们上一节的最后给大家说过,有一个叫routingKey的东西,好像我们暂时还没有使用过。本节讲的这两种模式都会使用到routingKey来实现我们的mq消费。

Routing模式

听这个名称就知道这个模式和路由有关,我们上一篇说的广播的模式这种方式有点缺少灵活性,他只是广播给所有人,假如我们有个场景是这样的:我们总共有10个消费者,而生产者前几条消息发送给前5个,后几条消息发送给之后的人,这时候如果使用广播模式发现无法达到我们的效果。这时候就发现广播这种模式不灵活,没法根据我们的想法传送消息。我们用direct路由器来替换它。direct路由器背后的路由算法很简单:只有当消息的路由键routing key与队列的绑定键binding key完全匹配时,该消息才会进入该队列。
这里写图片描述
我们从这个图可以看到我们的交换机和每一个队列中间都有个连线,这个连线都有一个值,其实这个值就是routingKey,而这个连线就相当于绑定,通过routingKey将交换机与队列进行绑定,这样的话,我们可以设置什么样的数据发给c1,什么样的数据发送给c2,只要设置相应的routingKey就能到达我们的要求,这种方式是不是很灵活。
其实代码实现也是很简单的

 private static String EXCHANGE_NAME="direct_name";
    @Autowired
    RabbitTemplate amqpt;

    @RequestMapping(value="test")
    public void test() throws InterruptedException{

            amqpt.convertAndSend(EXCHANGE_NAME,"direct", "hello word");
//          amqpt.convertAndSend
            System.err.println("消息发送成功");
    }

    @RequestMapping(value="test1")
    public void test1() throws InterruptedException{

            amqpt.convertAndSend(EXCHANGE_NAME,"direct1", "您好!");
            System.err.println("消息发送成功");
    }

我们看convertAndSend的参数,第一个是交换机的名称,第二个是routingKey,第三个是消息。到这里我们的生产者就已经完成了。我们看一下他们是如何绑定的

  private static String EXCHANGE_NAME="direct_name";
        @Bean
        public Queue queue(){
            return new Queue("direct_queue");
        }

        @Bean
        public Queue queue1(){
            return new Queue("direct_queue1");
        }

        @Bean
        public DirectExchange directExchange(){
            return new DirectExchange(EXCHANGE_NAME);
        }
        @Bean
        public Binding binddirect(Queue queue,DirectExchange directExchange){
            return BindingBuilder.bind(queue).to(directExchange).with("direct");
        }
        @Bean
        public Binding binddirect1(Queue queue1,DirectExchange directExchange){
            return BindingBuilder.bind(queue1).to(directExchange).with("direct");
        }
        @Bean
        public Binding binddirect2(Queue queue1,DirectExchange directExchange){
            return BindingBuilder.bind(queue1).to(directExchange).with("direct1");
        }

其实也很简单,因为我们路由模式下的交换机类型是direct,所以我们声明一个direct的交换机的,然后我们通过BindingBuilder.bind(queue).to(directExchange).with(“direct”)将交换机和队列通过routingKey绑定在一起,我们发现这个代码里面queue1通过direct1绑定到交换机,queue、queue1通过direct绑定到交换机。也就是我们发消息,只要通过这个交换机发送的消息含有routingKey为direct1就会发给queue1队列,含有routingKey为direct就会发给queue1队列和queue队列。
而消费者也什么都可以不用管,只需要监听相应的队列即可。
这种方式最大的特点就是灵活。

topic模式

topic模式也称为主题模式,其实他相对于routing模式最大的好处就是他多了一种匹配模式的路由,怎么理解匹配呢,其实就相当于我们之前正则的.*这种,不过他的匹配机制可能不是这种,而他的工作流程图如下
这里写图片描述
我们先讲一下他的匹配规则吧,其实除了匹配规则外,他的作用就和routing模式一样
绑定键binding key也必须是这种形式。以特定路由键发送的消息将会发送到所有绑定键与之匹配的队列中。但绑定键有两种特殊的情况:
①*(星号)仅代表一个单词
②#(井号)代表任意个单词
我们就拿上面的图解释,.orange.能匹配 a.orange.a,b.orange.a,aa.orange.bb等等
lay.#能匹配的就多了,他只要一lay.开头的都匹配,他可以匹配lay.a,lay.a.b,lay.b.c等。
这样是不是很方便,比如我们想将log的发给q1队列,其他的发给q2,那么我们只需要定义log.#、或者log.*,那么你发送给q1队列的数据就是log日志的消息。
所以这种方式对于处理一个分类的消息特别方便。
而他的实现也不是很难

  //声明一个交换机的名称
    private static String EXCHANGE_NAME="exchange_topic";
    @Autowired
    AmqpTemplate amqpt;

    @RequestMapping(value="test")
    public void test() throws InterruptedException{
            //第一个参数是交换机,第二个参数是routingKey,第三个参数是要发送的消息,支持实体对象
            amqpt.convertAndSend(EXCHANGE_NAME,"topic.name.c", "hello word");
//          amqpt.convertAndSend
            System.err.println("消息发送成功");
    }

    @RequestMapping(value="test1")
    public void test1() throws InterruptedException{

            amqpt.convertAndSend(EXCHANGE_NAME,"topic.a", "您好!");
            System.err.println("消息发送成功");
    }

而我们绑定的地方配置类如下

//这个交换机的名称要和我们发送消息的交换机名称一致
      private static String EXCHANGE_NAME="exchange_topic";
      //新建一个队列,名称为exchange_queue
        @Bean
        public Queue queue(){
            return new Queue("exchange_queue");
        }
          //新建一个队列,名称为exchange_queue1
        @Bean
        public Queue queue1(){
            return new Queue("exchange_queue1");
        }
        /**
         * 声明一个topic的交换机,不同类型的可以声明成不同的,比如fanout、direct等
         * @return
         */
        @Bean
        public TopicExchange topicExchange(){
            return new TopicExchange(EXCHANGE_NAME);
        }
        /**
         * 队列与交换机的绑定,通过routingKey来绑定,fanout模式是不需要routingKey的,因为他是直接绑定队列的
         * @param queue
         * @param topicExchange
         * @return
         */
        @Bean
        public Binding binddirect(Queue queue,TopicExchange topicExchange){
            return BindingBuilder.bind(queue).to(topicExchange).with("topic.#");
        }
        @Bean
        public Binding binddirect1(Queue queue1,TopicExchange topicExchange){
            return BindingBuilder.bind(queue1).to(topicExchange).with("topic.*");
        }

我们会发现queue1 和queue2 绑定的是通过这种#和*的方式绑定,然后写完消费者,启动分别访问test和test1的接口,你就会发现test接口会触发queue的队列,而test1接口会触发queue1和queue的消息,这个和我们讲的效果一样。大家可以自己动手实现以下

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值