RabbitMQ发布订阅模式-fanout、direct、topic

发布订阅模式

RabbitMQ 支持发布-订阅模式(Publish-Subscribe Pattern),它是一种消息传递模式,用于将消息广播到多个消费者。在发布-订阅模式中,消息的发送方称为发布者(Publisher),而消息的接收方称为订阅者(Subscriber)。发布者将消息发送到交换机(Exchange),而交换机负责将消息广播到与之绑定的多个队列(Queues)。每个订阅者都可以独立地创建一个队列,并将其绑定到交换机上,以接收消息。
具体的步骤如下:

  • 发布者将消息发送到交换机,而不是直接发送到队列。消息可以具有一个特定的路由键(Routing Key)。
  • 交换机根据其类型和消息的路由键,将消息广播到与之绑定的多个队列。
  • 每个订阅者创建一个独立的队列,并将其绑定到交换机上,以接收消息。
  • 每个订阅者独立地消费队列中的消息。
    这样,每个订阅者都能够独立地接收到发布者发送的消息,实现了消息的广播和多消费者的并行处理。在这里插入图片描述

一、Fanout交换机

Fanout Exchange(扇形交换机): 扇形交换机将消息广播到与之绑定的所有队列,无论路由键是否匹配。它是实现发布-订阅模式最常用的交换机类型。
在这里插入图片描述

package com.example.springamqp.发布订阅.fanout;

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 FanoutConfig {
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("fanout");
    }

    // 声明第一个队列
    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanout.queue1");
    }

    // 声明第二个队列
    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanout.queue2");
    }

    // 绑定队列1和交换机
    @Bean
    public Binding bindingQueue1(Queue fanoutQueue1, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(fanoutQueue1).to(fanoutExchange);
    }

    // 绑定队列2和交换机
    @Bean
    public Binding bindingQueue2(Queue fanoutQueue2, FanoutExchange fanoutExchange) {
        return BindingBuilder.bind(fanoutQueue2).to(fanoutExchange);
    }

}

package com.example.springamqp.发布订阅.fanout;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class FanoutRabbitMQManager {
    private final RabbitTemplate rabbitTemplate;

    @Autowired
    public FanoutRabbitMQManager(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }

    public void sendMessage(String exchangeName, String message) {
        rabbitTemplate.convertAndSend(exchangeName, null, message);
    }
}

package com.example.springamqp.发布订阅.fanout;

import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class FanoutCommandLineRunner implements CommandLineRunner {
    private final FanoutRabbitMQManager rabbitMQManager;

    @Autowired
    public FanoutCommandLineRunner(FanoutRabbitMQManager rabbitMQManager) {
        this.rabbitMQManager = rabbitMQManager;
    }

    @Override
    public void run(String... args) {
        rabbitMQManager.sendMessage("fanout", "Hello, RabbitMQ!");
    }

    @RabbitListener(queues = "fanout.queue1")
    public void receiveMessage1(String message){
        System.out.println("Received1 receive fanout message: " + message);
    }

    @RabbitListener(queues = "fanout.queue2")
    public void receiveMessage2(String message){
        System.out.println("Received2 receive fanout message: " + message);
    }
}

在这里插入图片描述
在这里插入图片描述

二、direct交换机

Direct Exchange(直连交换机): 直连交换机根据消息的路由键将消息发送到与之匹配的队列。在发布-订阅模式中,通常将直连交换机和具有相同路由键的队列一起使用,以实现消息的广播。
在这里插入图片描述

package com.example.springamqp.发布订阅.direct;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class DirectRabbitMQManager {
    private final RabbitTemplate rabbitTemplate;

    @Autowired
    public DirectRabbitMQManager(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }

    public void sendMessage(String exchangeName, String routingKey, String message) {
        rabbitTemplate.convertAndSend(exchangeName, routingKey, message);
    }
}

package com.example.springamqp.发布订阅.direct;

import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class DirectCommandLineRunner implements CommandLineRunner {
    private final DirectRabbitMQManager rabbitMQManager;

    @Autowired
    public DirectCommandLineRunner(DirectRabbitMQManager rabbitMQManager) {
        this.rabbitMQManager = rabbitMQManager;
    }

    @Override
    public void run(String... args) {
        rabbitMQManager.sendMessage("direct", "yellow", "Hello, RabbitMQ!");
    }

    @RabbitListener(
        bindings = @QueueBinding(
                value = @Queue(name = "direct.queue1"),
                exchange = @Exchange(name = "direct"),
                key = {"red", "yellow"}
        ))
    public void listenDirectQueue1(String message){
        System.out.println("Received1 receive direct message: " + message);
    }

    @RabbitListener(
            bindings = @QueueBinding(
                    value = @Queue(name = "direct.queue2"),
                    exchange = @Exchange(name = "direct"),
                    key = {"red", "blue"}
            ))
    public void listenDirectQueue2(String message){
        System.out.println("Received2 receive direct message: " + message);
    }

}

在这里插入图片描述

在这里插入图片描述

三、topic交换机

Topic Exchange(主题交换机): 主题交换机根据消息的主题(Topic)进行消息路由。订阅者可以使用通配符匹配来接收特定主题的消息。
在这里插入图片描述

package com.example.springamqp.发布订阅.topic;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class TopicRabbitMQManager {
    private final RabbitTemplate rabbitTemplate;

    @Autowired
    public TopicRabbitMQManager(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }

    public void sendMessage(String exchangeName, String routingKey, String message) {
        rabbitTemplate.convertAndSend(exchangeName, routingKey, message);
    }
}

package com.example.springamqp.发布订阅.topic;

import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class TopicCommandLineRunner implements CommandLineRunner {
    private final TopicRabbitMQManager rabbitMQManager;

    @Autowired
    public TopicCommandLineRunner(TopicRabbitMQManager rabbitMQManager) {
        this.rabbitMQManager = rabbitMQManager;
    }

    @Override
    public void run(String... args) {
        rabbitMQManager.sendMessage("topic", "china.news", "Hello, RabbitMQ!");
    }

    @RabbitListener(
        bindings = @QueueBinding(
                value = @Queue(name = "topic.queue1"),
                exchange = @Exchange(name = "topic", type = ExchangeTypes.TOPIC),
                key = "china.#"
        ))
    public void listenTopicQueue1(String message){
        System.out.println("Received1 receive topic message: " + message);
    }

    @RabbitListener(
            bindings = @QueueBinding(
                    value = @Queue(name = "topic.queue2"),
                    exchange = @Exchange(name = "topic", type = ExchangeTypes.TOPIC),
                    key = "#.news"
            ))
    public void listenTopicQueue2(String message){
        System.out.println("Received2 receive topic message: " + message);
    }

}

在这里插入图片描述

    @Override
    public void run(String... args) {
        rabbitMQManager.sendMessage("topic", "America.news", "Hello, RabbitMQ!");
    }

在这里插入图片描述

    @Override
    public void run(String... args) {
        rabbitMQManager.sendMessage("topic", "America.qq", "Hello, RabbitMQ!");
    }

在这里插入图片描述

    @Override
    public void run(String... args) {
        rabbitMQManager.sendMessage("topic", "chinachina.news", "Hello, RabbitMQ!");
    }

    @RabbitListener(
        bindings = @QueueBinding(
                value = @Queue(name = "topic.queue1"),
                exchange = @Exchange(name = "topic", type = ExchangeTypes.TOPIC),
                key = "china.*"
        ))
    public void listenTopicQueue1(String message){
        System.out.println("Received1 receive topic message: " + message);
    }

    @RabbitListener(
            bindings = @QueueBinding(
                    value = @Queue(name = "topic.queue2"),
                    exchange = @Exchange(name = "topic", type = ExchangeTypes.TOPIC),
                    key = "*.news"
            ))
    public void listenTopicQueue2(String message){
        System.out.println("Received2 receive topic message: " + message);
    }

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值