RabbitMQ的6种工作模式---工作队列模式and交换机模式(订阅模式)

上一篇说的RabbitMQ的6种工作模式---简单模式,这篇说一下工作队列模式和交换机模式(也叫订阅模式)

代码基于spring boot + JDK1.8,需要两个两个项目,springbootmqproducers(生产者)、springbootmq(两个消费者)

工作队列模式:

这种模式出现了多个消费者,为了保证消费者之间的负载均衡和同步,需要再消息队列之间加上同步功能。

主要思想:

避免立即执行资源密集型任务(耗时),以便下一个任务执行时不用等待它完成。工作队列将任务封装为消息并将其发送到队列中。

流程图:

代码:

代码在原来的基础上,再添加一个消费者DirectReceiverA,原来代码请查阅这里

package com.lyc.springbootmq.customer;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 监听的队列名称 lycDirectQueue
 * 第二个消费者
 */
@Component
@RabbitListener(queues = "lycDirectQueue")//监听的队列名称 TestDirectQueue
public class DirectReceiverA {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("第二个消费者收到消息  : " + testMessage.toString());
    }

}

然后启动生产者和消费者的两个项目,连续访问localhost:6060/rabbiMQDemo/sendDirectMessage

可以在控制台看到以下输出

说明这两个消费者都消费了。实现了负载均衡

交换机模式:

实际上,在前面两种模式已经使用了交换机,在生产者代码里,有配置交换机名称。

//Direct交换机 起名:LycDirectExchange
    @Bean
    DirectExchange LycDirectExchange() {
        return new DirectExchange("lycDirectExchange",true,false);
    }

让我们看一下DirectExchange的参数都有什么

name.:交换机名称;durable:是否持久化,一般填ture;autoDelete:用完是否自动删除

流程图:

如果消息配置的交换机配置的参数和RabbitMQ队列绑定(binding)的交换机名称相同,则转发。否则丢弃。此处交换机类型是fanout(扇形)

这种形式的需要多个队列,多个消费者,消费指定的信息,也就是一个消费者对应一个队列

代码如下:

在生产者新增配置代码,新增扇形交换机

package com.lyc.springbootmqproducers.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * 扇形交换机
 **/
@Configuration
public class FanoutRabbitConfig {

    /**
     *  创建三个队列 :fanout.A   fanout.B  fanout.C
     *  将三个队列都绑定在交换机 fanoutExchange 上
     *  因为是扇型交换机, 路由键无需配置,配置也不起作用
     */


    @Bean
    public Queue queueA() {
        return new Queue("QueueA");
    }

    @Bean
    public Queue queueB() {
        return new Queue("QueueB");
    }

    @Bean
    public Queue queueC() {
        return new Queue("QueueC");
    }

    @Bean
    FanoutExchange fanoutExchange() {
        return new FanoutExchange("fanoutExchange");
    }

    @Bean
    Binding bindingExchangeA() {
        return BindingBuilder.bind(queueA()).to(fanoutExchange());
    }

    @Bean
    Binding bindingExchangeB() {
        return BindingBuilder.bind(queueB()).to(fanoutExchange());
    }

    @Bean
    Binding bindingExchangeC() {
        return BindingBuilder.bind(queueC()).to(fanoutExchange());
    }
}

新增访问方法

@GetMapping("/sendFanoutMessage1")
    public String sendFanoutMessage() {
        String messageId = String.valueOf(UUID.randomUUID());
        String messageData = "message: testFanoutMessage ";
        Map<String, Object> map = new HashMap<>();
        map.put("messageData", messageData);
        rabbitTemplate.convertAndSend("fanoutExchange", null, map);
        return "ok";
    }

在消费者中新增三个消费者,分别监听三个队列

package com.lyc.springbootmq.customer;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 监听的队列名称 QueueC
 * 第三个消费者
 */
@Component
@RabbitListener(queues = "QueueC")//监听的队列名称 TestDirectQueue
public class DirectReceiverC {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("第三个消费者收到消息  : " + testMessage.toString());
    }

}
package com.lyc.springbootmq.customer;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 监听的队列名称 QueueB
 * 第一个消费者
 */
@Component
@RabbitListener(queues = "QueueA")//监听的队列名称 TestDirectQueue
public class DirectReceiverA {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("第一个消费者收到消息  : " + testMessage.toString());
    }

}
package com.lyc.springbootmq.customer;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 监听的队列名称 QueueB
 * 第二个消费者
 */
@Component
@RabbitListener(queues = "QueueB")//监听的队列名称 TestDirectQueue
public class DirectReceiverB {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("第二个消费者收到消息  : " + testMessage.toString());
    }

}

测试启动生产者,会发现MQ界面中出现三个队列

访问localhost:6060/rabbiMQDemo/sendFanoutMessage1,三个队列都会有一条消息

启动消费者项目会出现以下

说明这三个队列的消息全部被消费

好了,这两个模式说完了,现在小结一下

小结:

1.工作队列模式和交换机模式都是需要多个消费者

2.不同消费者可以监听同一个队列,可以负载均衡

3.不同消费者监听不同队列,可以实现注册后发邮件和发短信的业务

5.不同消费者监听不同队列,当交换机为fanout(广播)模式时,可以实现订阅功能

4.在扇形交换机中,路由键(routing key)失效,配置之后也不能用

下一篇继续说RabbitMQ的其他工作模式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值