RabbitMQ交换机以及各种类型

Exchanges交换机

生产者生产的消息从不会直接发送到队列,只能将消息发送到交换机

交换机一方面它接收来自生产者的消息,另一方面将它们推入队列。交换机必须确切知道如何处理收到的消息。是应该把这些消息放到特定队列还是说把他们放到许多队列中还是说应该丢弃它们。这些都是由交换机的类型来决定。

Exchanges的类型

  • 直接(direct)
  • 主题(topic)
  • 标题(headers)
  • 扇出(fanout)

Bindings绑定

交换机和队列之间的绑定
在这里插入图片描述

fanout扇出——发布/订阅模式

将接收到的所有消息广播到它知道的所有队列
在这里插入图片描述

生产者EmitLog 发送消息给两个消费者接收

public class EmitLog {

    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");

        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            String message = scanner.next();
            channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
            System.out.println("生产者发出消息:" + message);
        }
    }
}

消费者ReceiveLogs01接收消息

public class ReceiveLogs01 {

    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
        //声明一个临时队列
        String queueName = channel.queueDeclare().getQueue();
        //绑定交换机和队列
        channel.queueBind(queueName, EXCHANGE_NAME, "");

        System.out.println("ReceiveLogs01等待接收消息,将打印到控制台......");

        //声明接收消息回调函数 和 取消消息消费时的回调函数
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println("ReceiveLogs01控制台接收到消息:" + msg);
        };

        CancelCallback cancelCallback = (consumerTag) -> {
            System.out.println("取消消息消费");
        };

        //消费消息
        channel.basicConsume(queueName, true, deliverCallback, cancelCallback);

    }
}

消费者ReceiveLogs02接收消息

public class ReceiveLogs02 {

    public static final String EXCHANGE_NAME = "logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
        //声明一个临时队列
        String queueName = channel.queueDeclare().getQueue();
        //绑定交换机和队列
        channel.queueBind(queueName, EXCHANGE_NAME, "");

        System.out.println("ReceiveLogs02等待接收消息,将打印到控制台......");

        //声明接收消息回调函数 和 取消消息消费时的回调函数
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println("ReceiveLogs02控制台接收到消息:" + msg);
        };

        CancelCallback cancelCallback = (consumerTag) -> {
            System.out.println("取消消息消费");
        };

        //消费消息
        channel.basicConsume(queueName, true, deliverCallback, cancelCallback);

    }
}

当生产者发送消息时,两个消费者都可以接收到消息,这就是发布订阅模式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Direct直接交换机——路由模式

direct交换机和fanout交换机的区别在于RoutingKeyfanout交换机的RoutingKey相同从而实现了广播效果,而direct交换机的RoutingKey不相同从而选择性的推入消息到指定队列

在这里插入图片描述
生成者EmitLogDirect发送消息,可以指定消息通过交换机发送给哪个队列

public class EmitLogDirect {

    public static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");

        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            String message = scanner.next();
            channel.basicPublish(EXCHANGE_NAME, "info", null, message.getBytes("UTF-8"));
            System.out.println("生产者发出消息:" + message);
        }
    }
}

消费者ReceiveLogsDirect01接收消息

public class ReceiveLogsDirect01 {

    public static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        //声明一个临时队列
        channel.queueDeclare("console",false,false,false,null);
        //绑定交换机和队列
        channel.queueBind("console", EXCHANGE_NAME, "info");
        channel.queueBind("console", EXCHANGE_NAME, "warning");

        System.out.println("ReceiveLogsDirect01等待接收消息,将打印到控制台......");

        //声明接收消息回调函数 和 取消消息消费时的回调函数
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println("ReceiveLogsDirect01控制台接收到消息:" + msg);
        };

        CancelCallback cancelCallback = (consumerTag) -> {
            System.out.println("取消消息消费");
        };

        //消费消息
        channel.basicConsume("console", true, deliverCallback, cancelCallback);

    }
}

消费者ReceiveLogsDirect02接收消息

public class ReceiveLogsDirect02 {

    public static final String EXCHANGE_NAME = "direct_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明一个交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "direct");
        //声明一个临时队列
        channel.queueDeclare("disk",false,false,false,null);
        //绑定交换机和队列
        channel.queueBind("disk", EXCHANGE_NAME, "error");

        System.out.println("ReceiveLogsDirect02等待接收消息,将打印到控制台......");

        //声明接收消息回调函数 和 取消消息消费时的回调函数
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println("ReceiveLogsDirect02控制台接收到消息:" + msg);
        };

        CancelCallback cancelCallback = (consumerTag) -> {
            System.out.println("取消消息消费");
        };

        //消费消息
        channel.basicConsume("disk", true, deliverCallback, cancelCallback);

    }
}

生成者指定将消息发送给info队列
在这里插入图片描述
ReceiveLogsDirect01接收到消息,而ReceiveLogsDirect02不会接收到消息
在这里插入图片描述
在这里插入图片描述

Topic主题交换机

发送到类型是 topic 交换机的消息的 routing_key 不能随意写,必须满足一定的要求,它必须是一个单词列表,以点号分隔开*可以代替一个单词#可以替代零个多个单词。当一个队列绑定键是#,那么这个队列将接收所有数据,类似于 fanout 类型的交换机,如果队列绑定键当中没有#*出现,那么该队列绑定类型就是 direct
在这里插入图片描述
消费者ReceiveLogsTopic01

public class ReceiveLogsTopic01 {

    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "topic");
        //声明队列
        String queueName = "Q1";
        channel.queueDeclare(queueName, false, false, false, null);
        //绑定交换机和队列
        channel.queueBind(queueName, EXCHANGE_NAME, "*.orange.*");

        System.out.println("ReceiveLogsTopic01等待接收消息......");

        //声明接收消息回调函数 和 取消消息消费时的回调函数
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println("ReceiveLogsTopic01接收队列:" + queueName + " 绑定键:" + message.getEnvelope().getRoutingKey() + " 接收的消息:" + msg);
        };

        CancelCallback cancelCallback = (consumerTag) -> {
            System.out.println("取消消息消费");
        };

        channel.basicConsume("Q1", false, deliverCallback, cancelCallback);
    }
}

消费者ReceiveLogsTopic02

public class ReceiveLogsTopic02 {

    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();
        //声明交换机
        channel.exchangeDeclare(EXCHANGE_NAME, "topic");
        //声明队列
        String queueName = "Q2";
        channel.queueDeclare(queueName, false, false, false, null);
        //绑定交换机和队列
        channel.queueBind(queueName, EXCHANGE_NAME, "*.*.rabbit");
        channel.queueBind(queueName, EXCHANGE_NAME, "lazy.#");

        System.out.println("ReceiveLogsTopic02等待接收消息......");

        //声明接收消息回调函数 和 取消消息消费时的回调函数
        DeliverCallback deliverCallback = (consumerTag, message) -> {
            String msg = new String(message.getBody(), "UTF-8");
            System.out.println("ReceiveLogsTopic02接收队列:" + queueName + " 绑定键:" + message.getEnvelope().getRoutingKey() + " 接收的消息:" + msg);
        };

        CancelCallback cancelCallback = (consumerTag) -> {
            System.out.println("取消消息消费");
        };

        channel.basicConsume("Q1", false, deliverCallback, cancelCallback);
    }
}

生产者EmitLogTopic发出消息

public class EmitLogTopic {

    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMqUtils.getChannel();

        Map<String, String> bindingKeyMap = new HashMap<>();
        bindingKeyMap.put("aaa.orange.rabbit", "被队列Q1,Q2接收到");
        bindingKeyMap.put("lazy.orange.bbb", "被队列Q1,Q2接收到");
        bindingKeyMap.put("ccc.orange.ddd", "被队列Q1接收到");
        bindingKeyMap.put("lazy.eee.fff", "被队列Q2接收到");
        bindingKeyMap.put("lazy.ggg.rabbit", "虽然满足两个绑定但只被队列Q2接收一次");
        bindingKeyMap.put("hhh.iii.jjj", "不匹配任何绑定,被丢弃");
        bindingKeyMap.put("kkk.orange.lll.rabbit", "四个单词不匹配任何绑定,被丢弃");
        bindingKeyMap.put("lazy.orange.male.rabbit", "被队列Q2接收到");

        for (Map.Entry<String, String> bindingKeyEntry : bindingKeyMap.entrySet()) {
            String routingKey = bindingKeyEntry.getKey();
            String message = bindingKeyEntry.getValue();
            channel.basicPublish(EXCHANGE_NAME, routingKey, null, message.getBytes("UTF-8"));
            System.out.println("生产者发出消息:" + message);
        }

    }
}

生产者发出消息
在这里插入图片描述
消费者ReceiveLogsDirect01接收消息
在这里插入图片描述
消费者ReceiveLogsDirect02接收消息
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值