Rabbit Mq 五种模式 + Spring Boot 实现

请添加图片描述
简单模式:

  1. 一个生产者,一个队列,一个消费者

Config:

/**
 * @author Fly_Roushan
 * @date 2021/8/23
 */
@Configuration
public class RabbitConfig {

    /**
     * 简单模式不需要绑定交换机
     *
     * @return
     */
    @Bean
    public Queue simpleQueue() {
        return new Queue(RabbitConst.SIMPLE_QUEUE, true);
    }
}

Producer:

/**
 * @author Fly_Roushan
 * @date 2021/8/23
 */
@Component
public class Producer {

    private static final Logger LOGGER = LoggerFactory.getLogger(Producer.class);

    @Autowired
    private AmqpTemplate amqpTemplate;

    /**
     * Simple Mode
     *
     */
    public void sendMessage() {
        String data = "Simple Test";
        LOGGER.info("[Producer] Send: {}", data);
        amqpTemplate.convertAndSend(RabbitConst.SIMPLE_QUEUE, data);
    }
}

Consumer:

/**
 * @author Fly_Roushan
 * @date 2021/8/23
 */
@Component
public class Consumer {

    private static final Logger LOGGER = LoggerFactory.getLogger(Consumer.class);

    @RabbitListener(queues = RabbitConst.SIMPLE_QUEUE)
    @RabbitHandler
    public void simpleConsumer(String data, Channel channel, Message message) {
        LOGGER.info("[Consumer] Consume: {}", data);
    }
}

结果:
在这里插入图片描述

请添加图片描述
工作模式:

  1. 一个生产者,一个队列,多个消费者
  2. 消费时采用轮询的方式

Config:

    /**
     * 工作模式不需要绑定交换机
     *
     * @return
     */
    @Bean
    public Queue workQueue() {
        return new Queue(RabbitConst.WORK_QUEUE, true);
    }

Producer:

    /**
     * Work Mode
     */
    public void workMessage() {
        String data = "Work Test";
        LOGGER.info("[Producer] Send: {}", data);
        amqpTemplate.convertAndSend(RabbitConst.WORK_QUEUE, data);
    }

Consumer:

    @RabbitListener(queues = RabbitConst.WORK_QUEUE)
    @RabbitHandler
    public void workConsumer1(String data, Channel channel, Message message) {
        LOGGER.info("[Consumer] Consume 1: {}", data);
        ack(channel, message);
    }

    @RabbitListener(queues = RabbitConst.WORK_QUEUE)
    @RabbitHandler
    public void workConsumer2(String data, Channel channel, Message message) {
        LOGGER.info("[Consumer] Consume 2: {}", data);
        ack(channel, message);
    }

结果:
在这里插入图片描述

请添加图片描述
订阅模式(fanout):

  1. 一个生产者,一个交换机,多个队列,多个消费者
  2. 一个队列,可以使用多个消费者来进行轮询消费
  3. 所有的队列都会接受到生产者的消息

Config:

    /**
     * 用于绑定fanout交换机
     *
     * @return
     */
    @Bean
    public Queue fanoutQueue() {
        return new Queue(RabbitConst.FANOUT_QUEUE, true);
    }

    /**
     * 订阅模式需要声明特别的交换机
     *
     * @return
     */
    @Bean
    public FanoutExchange fanoutExchange() {
        return new FanoutExchange(RabbitConst.FANOUT_EXCHANGE);
    }

    /**
     * 根据实际需求绑定到fanout交换机
     *
     * @return
     */
    @Bean
    public Binding bandwidthFanout() {
        return BindingBuilder.bind(fanoutQueue()).to(fanoutExchange());
    }

Producer:

    /**
     * Fanout Mode
     * 这里不用指定队列,也就是RoutingKey,只需要指定对哪个交换机发送消息即可
     */
    public void fanoutMessage() {
        String data = "Fanout Test";
        LOGGER.info("[Producer] Send: {}", data);
        amqpTemplate.convertAndSend(RabbitConst.FANOUT_EXCHANGE, null, data);
    }

Consumer:

    /**
     * 简单说一下,这里使用的是随机队列。
     * 队列在有消费者声明的时候存在,没有就会自动消失。
     *
     * @param data
     * @param channel
     * @param message
     */
    @RabbitListener(bindings = @QueueBinding(value = @Queue(), exchange = @Exchange(value = RabbitConst.FANOUT_EXCHANGE, type = ExchangeTypes.FANOUT)))
    @RabbitHandler
    public void fanoutConsumer1(String data, Channel channel, Message message) {
        LOGGER.info("[Consumer] Fanout Consume 1: {}", data);
        ack(channel, message);
    }

    @RabbitListener(bindings = @QueueBinding(value = @Queue(), exchange = @Exchange(value = RabbitConst.FANOUT_EXCHANGE, type = ExchangeTypes.FANOUT)))
    @RabbitHandler
    public void fanoutConsumer2(String data, Channel channel, Message message) {
        LOGGER.info("[Consumer] Fanout Consume 2: {}", data);
        ack(channel, message);
    }

    @RabbitListener(queues = RabbitConst.FANOUT_QUEUE)
    @RabbitHandler
    public void fanoutConsumer3(String data, Channel channel, Message message) {
        LOGGER.info("[Consumer] Fanout Consume 3: {}", data);
        ack(channel, message);
    }

结果:
在这里插入图片描述

请添加图片描述
路由模式(direct):

  1. 一个生产者,一个交换机,多个队列
  2. 消息发送给完全匹配RoutingKey的队列
  3. 一个队列可以绑定多个RoutingKey

Config:

    /**
     * 一个平平无奇的Queue
     *
     * @return
     */
    @Bean
    public Queue directQueue1() {
        return new Queue(RabbitConst.DIRECT_QUEUE_1);
    }

    /**
     * 一个平平无奇的Queue
     *
     * @return
     */
    @Bean
    public Queue directQueue2() {
        return new Queue(RabbitConst.DIRECT_QUEUE_2);
    }

    /**
     * 声明对应交换机
     *
     * @return
     */
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(RabbitConst.DIRECT_EXCHANGE);
    }

    /**
     * 绑定三连
     * 一个Queue, 一个Routing Key
     *
     * @return
     */
    @Bean
    public Binding directBinding1() {
        return BindingBuilder.bind(directQueue1()).to(directExchange()).with(RabbitConst.DIRECT_KEY_1);
    }

    /**
     * 一个Queue, 两个Routing Key
     * 队列相同,with方法那里的RoutingKey不同
     * 
     * @return
     */
    @Bean
    public Binding directBinding2() {
        return BindingBuilder.bind(directQueue2()).to(directExchange()).with(RabbitConst.DIRECT_KEY_2);
    }

    @Bean
    public Binding directBinding3() {
        return BindingBuilder.bind(directQueue2()).to(directExchange()).with(RabbitConst.DIRECT_KEY_3);
    }

Producer:

    /**
     * Direct Mode
     *
     * @param routingKey
     */
    public void directMessage(String routingKey) {
        String data = "Direct Test " + routingKey;
        LOGGER.info("[Producer] Send: {}", data);
        amqpTemplate.convertAndSend(RabbitConst.DIRECT_EXCHANGE, routingKey, data);
    }

Consumer:

    @RabbitListener(queues = RabbitConst.DIRECT_QUEUE_1)
    @RabbitHandler
    public void directConsumer1(String data, Channel channel, Message message) {
        LOGGER.info("[Consumer] Direct Consume 1: {}", data);
        ack(channel, message);
    }

    @RabbitListener(queues = RabbitConst.DIRECT_QUEUE_2)
    @RabbitHandler
    public void directConsumer2(String data, Channel channel, Message message) {
        LOGGER.info("[Consumer] Direct Consume 2: {}", data);
        ack(channel, message);
    }

结果:
在这里插入图片描述
请添加图片描述
主题模式(topic):

  1. 一个生产者,一个交换机,多个队列
  2. 消息发送给满足匹配规则的队列
  3. 一个队列可以绑定多个RoutingKey

Config:

    /**
     * 平平无奇的队列
     */
    @Bean
    public Queue topicQueue() {
        return new Queue(RabbitConst.TOPIC_QUEUE);
    }

    /**
     * with输入匹配规则
     * 匹配规则:
     * *代表一个单词
     * #代表一个或多个单词
     * *和#都可以代表任意字符或空
     * 多个字符用.连接
     * 
     * eg. 
     * TOPIC.*.TEST 可以匹配 TOPIC.TEST     TOPIC.AA.TEST   不能匹配TOPIC.AA.BB.TEST
     * TOPIC.#.TEST 可以匹配 TOPIC.TEST     TOPIC.AA.TEST   TOPIC.AA.BB.TEST
     *
     * @return
     */
    @Bean
    public Binding topicBinding() {
        return BindingBuilder.bind(topicQueue()).to(topicExchange()).with("TOPIC.#.TEST");
    }

Producer:

    /**
     * Topic Mode
     *
     * @param routingKey
     */
    public void topicMessage(String routingKey) {
        String data = "Topic Test " + routingKey;
        LOGGER.info("[Producer] Send: {}", data);
        amqpTemplate.convertAndSend(RabbitConst.TOPIC_EXCHANGE, routingKey, data);
    }

Consumer:

    @RabbitListener(queues = RabbitConst.TOPIC_QUEUE)
    @RabbitHandler
    public void topicConsumer(String data, Channel channel, Message message) {
        LOGGER.info("[Consumer] Topic Consume: {}", data);
        ack(channel, message);
    }

结果:
在这里插入图片描述

总结:

  1. 在我看来,工作模式和简单模式更像是针对队列的处理,在其他模式中也适用,广播时,也可以为一个队列来准备多个消费者分担压力。
  2. 传递对象链接:https://blog.csdn.net/qq_43010427/article/details/119827784

如有不准确之处,欢迎大家指出~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值