【RabbitMQ】SpringBoot集成RabbitMQ项目实战:简单队列模式、三种交换机模式(Fanout模式,Direct模式,Topic模式))

1 本文背景

近期在做一个电商秒杀项目,在服务优化的阶段用到了 RabbitMQ 这个消息中间件,让秒杀请求不再瞬时冲击秒杀接口,而是利用消息中间件来让请求如队列般排队而来。

2 集成 RabbitMQ 简单消息队列模式

在这里插入图片描述

2.1 步骤

下面首先介绍最基础的一种 SpringBoot 集成 RabbitMQ 简单消息队列模式的方式:添加 pom 依赖、 yml 配置、配置类、消息发送者、消息接收者

1、添加 pom 依赖,这里需要添加 amqp,amqp 是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计,基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2、yaml 配置文件,各参数说明已给出注释

spring:
	rabbitmq:
        host: 192.168.10.132
        username: guest
        password: guest
        # 虚拟主机
        virtual-host: /
        port: 5672
        listener:
          simple:
            # 消费者最小数量
            concurrency: 10
            # 消费者最大数量
            max-concurrency: 10
            # 限制消费者每次只处理一条消息,处理完再继续下一条消息
            prefetch: 1
            # 启动时是否默认启动容器,默认true
            auto-startup: true
            # 被拒绝时重新进入队列
            default-requeue-rejected: true
        template:
          retry:
            # 发布重试,默认false
            enabled: true
            # 重试时间 默认1000ms
            initial-interval: 1000
            # 重试最大次数,默认3次
            max-attempts: 3
            # 重试最大间隔时间,默认10000ms
            max-interval: 1000
            # 重试间隔的乘数。比如配2.0 第一次等10s,第二次等20s,第三次等40s
            multiplier: 1.0

3、配置类

@Configuration
public class RabbitMQConfig {
    @Bean
    public Queue queue() {
        return new Queue("queue", true);
    }
}

4、消息生产者(发送者)

@Service
@Slf4j
public class MQSender {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void send(Object msg) {
        log.info("发送消息:" + msg);
        rabbitTemplate.convertAndSend("queue", msg);
    }
}

5、消息消费者(接收者)

@Service
@Slf4j
public class MQReceiver {

    @RabbitListener(queues = "queue")
    public void receive(Object msg) {
        log.info("接收消息:" + msg);
    }
}

2.2 测试结果

这里写一个接口调用消息发送者进行消息的发送

/**
* 测试 rabbitmq
 */
@RequestMapping("/mq")
@ResponseBody
public void mq() {
    mqSender.send("Hello");
}

访问此请求
在这里插入图片描述

日志打印情况
在这里插入图片描述

rabbitmq_management UI 管控页面的情况
在这里插入图片描述
可见,根据上述测试情况,简单模式下,消息生产者与消息消费者已对接成功。

3 集成 RabbitMQ Fanout 交换机模式

Fanout 交换机模式对应 RabbitMQ 消息队列的发布/订阅模式,此模式不处理路由键,只需要简单的将队里绑定到交换机上发送到交换机的消息都会被转发到与该交换机绑定的所有队列上Fanout交换机转发消息是最快的。
在这里插入图片描述

3.1 步骤

在上述 2 中的简单队列模式中修改配置类,改为两个队列、一个交换机

@Configuration
public class RabbitMQConfig {
    private static final String QUEUE01 = "queue_fanout01";
    private static final String QUEUE02 = "queue_fanout02";
    private static final String EXCHANGE = "fanoutExchange";

    @Bean
    public Queue queue01() {
        return new Queue(QUEUE01);
    }
    @Bean
    public Queue queue02() {
        return new Queue(QUEUE02);
    }

    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(EXCHANGE);
    }

    @Bean
    public Binding binding01() {
        return BindingBuilder.bind(queue01()).to(fanoutExchange());
    }
    @Bean
    public Binding binding02() {
        return BindingBuilder.bind(queue02()).to(fanoutExchange());
    }
}

消息发送方中,设置交换机名

@Service
@Slf4j
public class MQSender {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void send(Object msg) {
        log.info("发送消息:" + msg);
        rabbitTemplate.convertAndSend("fanoutExchange", "", msg);
    }
}

消息接收方中配置两个监听的接收者

@Service
@Slf4j
public class MQReceiver {

    @RabbitListener(queues = "queue_fanout01")
    public void receive01(Object msg) {
        log.info("QUEUE01接受消息:" + msg);
    }

    @RabbitListener(queues = "queue_fanout02")
    public void receive02(Object msg) {
        log.info("QUEUE02接受消息:" + msg);
    }
}

3.2 测试结果

编写测试接口

/**
 *fanout模式:测试 rabbitmq
 */
@RequestMapping("/mq/fanout")
@ResponseBody
public void mq01() {
    mqSender.send("Hello");
}

再次运行项目后,在 UI 管控页面即可看到我们自己注册的交换机
在这里插入图片描述
点开此交换机后也可看到我们绑定的两个队列

在这里插入图片描述

访问此请求进行 Fanout 模式交换机的测试
在这里插入图片描述

日志打印情况
在这里插入图片描述

rabbitmq_management UI 管控页面的情况

在这里插入图片描述

4 集成 RabbitMQ Direct 交换机模式

Direct 交换机模式对应 RabbitMQ 消息队列的路由模式,所有发送到Direct Exchange的消息被转发到RouteKey中指定的Queue,注意,Direct模式可以使用RabbitMQ自带的Exchange(default Exchange),所以不需要将Exchange进行任何绑定(binding)操作,消息传递时,RouteKey必须完全匹配才会被队列接收,否则该消息会被抛弃。重点:routing key与队列queues 的key保持一致,即可以路由到对应的queue中。
在这里插入图片描述

4.1 步骤

配置类

@Configuration
public class RabbitMQConfigDirect {
    private static final String QUEUE01 = "queue_direct01";
    private static final String QUEUE02 = "queue_direct02";
    private static final String EXCHANGE = "directExchange";
    private static final String ROUTINGKEY01 = "queue.red";
    private static final String ROUTINGKEY02 = "queue.green";

    @Bean
    public Queue queue01() {
        return new Queue(QUEUE01);
    }

    @Bean
    public Queue queue02() {
        return new Queue(QUEUE02);
    }

    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(EXCHANGE);
    }

    @Bean
    public Binding binding01() {
        return BindingBuilder.bind(queue01()).to(directExchange()).with(ROUTINGKEY01);
    }

    @Bean
    public Binding binding02() {
        return BindingBuilder.bind(queue02()).to(directExchange()).with(ROUTINGKEY02);
    }
}

消息发送方

@Service
@Slf4j
public class MQSender {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void send01(Object msg) {
        log.info("发送red消息:" + msg);
        rabbitTemplate.convertAndSend("directExchange", "queue.red", msg);
    }

    public void send02(Object msg) {
        log.info("发送green消息:" + msg);
        rabbitTemplate.convertAndSend("directExchange", "queue.green", msg);
    }
}

消息接收方

@Service
@Slf4j
public class MQReceiver {

    @RabbitListener(queues = "queue_direct01")
    public void receive01(Object msg) {
        log.info("QUEUE01接受消息:" + msg);
    }

    @RabbitListener(queues = "queue_direct02")
    public void receive02(Object msg) {
        log.info("QUEUE02接受消息:" + msg);
    }
}

4.2 测试结果

编写测试接口

/**
 * 测试 RabbitMQ
 */
@RequestMapping("/mq/direct01")
@ResponseBody
public void mq01() {
    mqSender.send01("Hello,Red");
}

/**
 * 测试 RabbitMQ
 */
@RequestMapping("/mq/direct02")
@ResponseBody
public void mq02() {
    mqSender.send02("Hello,Green");
}

访问测试请求
在这里插入图片描述
在这里插入图片描述

5 集成 RabbitMQ Topic 交换机模式

Topic 交换机模式对应 RabbitMQ 消息队列的主题模式,所有发送到Topic Exchange的消息被转发到所有管线RouteKey中指定Topic的Queue上Exchange将RouteKey和某Topic进行模糊匹配,此时队列需要绑定一个Topic,对于routing key匹配模式定义规则举例如下:
在这里插入图片描述

5.1 步骤

配置类

@Configuration
public class RabbitMQConfigTopic {
    private static final String QUEUE01 = "queue_topic01";
    private static final String QUEUE02 = "queue_topic02";
    private static final String EXCHANGE = "topicExchange";
    private static final String ROUTINGKEY01 = "#.queue.#";
    private static final String ROUTINGKEY02 = "*.queue.#";

    @Bean
    public Queue queue01() {
        return new Queue(QUEUE01);
    }

    @Bean
    public Queue queue02() {
        return new Queue(QUEUE02);
    }

    @Bean
    public TopicExchange topicExchange() {
        return new TopicExchange(EXCHANGE);
    }

    @Bean
    public Binding binding01() {
        return BindingBuilder.bind(queue01()).to(topicExchange()).with(ROUTINGKEY01);
    }

    @Bean
    public Binding binding02() {
        return BindingBuilder.bind(queue02()).to(topicExchange()).with(ROUTINGKEY02);
    }
}

消息发送方

@Service
@Slf4j
public class MQSender {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void send01(Object msg) {
        log.info("发送消息(被01队列接受):" + msg);
        rabbitTemplate.convertAndSend("topicExchange", "queue.red.message", msg);
    }

    public void send02(Object msg) {
        log.info("发送消息(被两个queue接受):" + msg);
        rabbitTemplate.convertAndSend("topicExchange", "message.queue.green.abc", msg);
    }
}

消息接收方

@Service
@Slf4j
public class MQReceiver {

    @RabbitListener(queues = "queue_topic01")
    public void receive01(Object msg) {
        log.info("QUEUE01接受消息:" + msg);
    }

    @RabbitListener(queues = "queue_topic02")
    public void receive02(Object msg) {
        log.info("QUEUE02接受消息:" + msg);
    }
}

5.2 测试结果

编写测试接口

/**
* 测试 RabbitMQ
 */
@RequestMapping("/mq/topic01")
@ResponseBody
public void mq01() {
    mqSender.send01("Hello,Red");
}

/**
 * 测试 RabbitMQ
 */
@RequestMapping("/mq/topic02")
@ResponseBody
public void mq02() {
    mqSender.send02("Hello,Green");
}

访问测试请求
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超周到的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值